//--------------------------------------------------------------------------- // Copyright (c) 1991,1992 Southeastern Universities Research Association, // Continuous Electron Beam Accelerator Facility // // This software was developed under a United States Government license // described in the NOTICE file included as part of this distribution. //---------------------------------------------------------------------------- // // description: cdevSelector.h // The cdevSelector class provides a mechanism for cdevServices to provide // a locally changable file descriptor to the cdevSystem for select // operations. // // If the service does not support or require file descriptors to operate, // it may make one of these objects in its constructor and then provide // the 'readfd' to the cdevSystem when it calls the services getFD method. // The service may then 'insertEvents' into the object, which will in-turn // cause the cdevSystems select mechanism to call the service. Once the // service has responded to the events it should call 'removeEvents' to // prevent the select mechanism from being triggered again. // // Author: Walt Akers // // Revision History: // cdevSelector.h,v // Revision 1.3 1996/12/05 21:10:49 akers // Changes to support multiple CDEV DDL versions // // Revision 1.2 1995/10/19 20:16:55 akers // Added capability to test the read file descriptor for data before reading // // Revision 1.1 1995/08/18 16:23:41 akers // Mechanism for providing file descriptor selection for services. // // #ifndef _CDEV_SELECTOR_H_ #define _CDEV_SELECTOR_H_ #include #include #include #include #include #if defined(solaris) || defined(SunOS) #include #endif class cdevSelector { private: typedef struct { int readfd; int writefd; } SocketPair; SocketPair sp; char cbuf[21]; public: cdevSelector ( void ); ~cdevSelector ( void ); int insertEvent ( int numEvents = 1 ); int removeEvent ( int numEvents = 1 ); void purge ( void ); int writefd ( void ); int readfd ( void ); }; // ***************************************************************************** // * cdevSelector::cdevSelector : // * Constructor for the cdevSelector class. // ***************************************************************************** inline cdevSelector::cdevSelector ( void ) { if(pipe((int *)&sp)!=0) { sp.readfd = -1; sp.writefd = -1; } else { int val; val = ::fcntl(sp.readfd, F_GETFL, 0); if(val>0) ::fcntl(sp.readfd, F_SETFL, val|O_NONBLOCK); val = ::fcntl(sp.writefd, F_GETFL, 0); if(val>0) ::fcntl(sp.writefd, F_SETFL, val|O_NONBLOCK); } } // ***************************************************************************** // * cdevSelector::~cdevSelector : // * Destructor for the cdevSelector class. // ***************************************************************************** inline cdevSelector::~cdevSelector ( void ) { if(sp.readfd != -1) close(sp.readfd); if(sp.writefd != -1) close(sp.writefd); } // ***************************************************************************** // * cdevSelector::insertEvent : // * Adds one or more bytes (indicating events) to the pipe // ***************************************************************************** inline int cdevSelector::insertEvent ( int numEvents ) { int result = 0; char *cptr = cbuf; // ********************************************************************* // * If the write file descriptor is valid // ********************************************************************* if(sp.writefd>0) { // ************************************************************* // * If the user wants to add more bytes than the buffer can // * handle, allocated a sufficient buffer to hold the data. // ************************************************************* if(numEvents>20) cptr = new char[numEvents]; // ************************************************************* // * Write the specified number of bytes to the buffer. // ************************************************************* write(sp.writefd, cptr, numEvents); // ************************************************************* // * Delete the buffer if it was allocated locally. // ************************************************************* if(cptr!=cbuf) delete cptr; } else result = -1; return result; } // ***************************************************************************** // * cdevSelector::removeEvent : // * Removes one or more bytes (indicating events) from the pipe. // ***************************************************************************** inline int cdevSelector::removeEvent ( int numEvents ) { int result = 0; char *cptr = cbuf; // ********************************************************************* // * If the read file descriptor is valid. // ********************************************************************* if(sp.readfd>0) { int count; // ************************************************************* // * Find out how many bytes are ready to read. // ************************************************************* ioctl(sp.readfd, FIONREAD, &count); if(numEvents>count) numEvents = count; if(numEvents>0) { // ***************************************************** // * If the user wants to remove more bytes than the // * buffer can handle, allocated a sufficient buffer to // * hold the data. // ***************************************************** if(numEvents>20) cptr = new char[numEvents]; // ***************************************************** // * Read the specified number of bytes from the pipe. // ***************************************************** read(sp.readfd, cptr, numEvents); // ***************************************************** // * Delete the buffer if it was allocated locally. // ***************************************************** if(cptr!=cbuf) delete cptr; } } else result = -1; return result; } // ***************************************************************************** // * cdevSelector::purge : // * This function removes all bytes from the pipe. // ***************************************************************************** inline void cdevSelector::purge ( void ) { int count; char * cptr = cbuf; if(sp.readfd>0) { // ************************************************************* // * Find out how many bytes are ready to read. // ************************************************************* ioctl(sp.readfd, FIONREAD, &count); if(count>0) { // ***************************************************** // * If the user wants to remove more bytes than the // * buffer can handle, allocated a sufficient buffer to // * hold the data. // ***************************************************** if(count>20) cptr = new char[count]; // ***************************************************** // * Read the specified number of bytes from the pipe. // ***************************************************** read(sp.readfd, cptr, count); // ***************************************************** // * Delete the buffer if it was allocated locally. // ***************************************************** if(cptr!=cbuf) delete cptr; } } } // ***************************************************************************** // * cdevSelector::writefd // * Returns the write file descriptor associated with the pipe. // ***************************************************************************** inline int cdevSelector::writefd ( void ) { return sp.writefd; } // ***************************************************************************** // * cdevSelector::readfd // * Returns the read file descriptor associated with the pipe. // ***************************************************************************** inline int cdevSelector::readfd ( void ) { return sp.readfd; } #endif /* _CDEV_SELECTOR_H_ */