//----------------------------------------------------------------------------- // Copyright (c) 1994,1995 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: // FD_Set Wrapper Based on ACE // #include "cdevHandleSet.h" #ifndef __VMS #ifndef __linux extern "C" bzero (char *, int); #endif #else extern "C" bzero (char *, unsigned int); #endif #if defined(__VMS) && defined(_TGV_MULTINET) // ********************************************************************* // * Unfortunately when you use TGV Multinet, the bit offsets in the // * file * descriptor bitmasks used by select() cannot be found by // * simply using the value of the file descriptor. Fortunately, there // * is a simple relationship between the file descriptor value and the // * desired bit offset. // * (These macros are required because this file accesses the file // * descriptor bitmasks directly, without using the FD_SET(), FD_CLR(), // * FD_ISSSET() macros). // ********************************************************************* #define FD_TO_BIT_OFFSET( fd ) ((fd)/CHANNELSIZE) #define FD_FROM_BIT_OFFSET( ibit ) ((ibit)*CHANNELSIZE) #else // ********************************************************************* // * Under most operating systems the file descriptor value and the // * associated bit offset are one and the same. // ********************************************************************* #define FD_TO_BIT_OFFSET( fd ) (fd) #define FD_FROM_BIT_OFFSET( ibit ) (ibit) #endif #ifdef CDEV_HAS_UNDERSCORE_FDBITS #define fds_bits __fds_bits #endif inline int BIT_ENABLED (unsigned long word, int bit = 1) { return (word & bit) != 0; } inline int BIT_DISABLED (unsigned long word, int bit = 1) { return (word & bit) == 0; } inline void SET_BIT (unsigned long &word, int bit) { word |= bit; } inline void CLR_BIT (unsigned long &word, int bit) { word &= ~bit; } const char cdevHandleSet::nbits_[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, }; // ***************************************************************************** // * Counts the number of bits enabled in N. Uses a table lookup to speed up // * the count. // ***************************************************************************** int cdevHandleSet::count_bits (unsigned long n) const { return (cdevHandleSet::nbits_[n & 0xff] + cdevHandleSet::nbits_[(n >> 8) & 0xff] + cdevHandleSet::nbits_[(n >> 16) & 0xff] + cdevHandleSet::nbits_[n >> 24]); } void cdevHandleSetIterator::operator++ (void) { #ifdef _WIN32 this->index_++; #else this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; this->num_++; if (this->val_ == 0) { for (this->index_++; this->index_ < cdevHandleSet::NUM_WORDS && fds_.mask_.fds_bits[this->index_] == 0; this->index_++); if (this->index_ == cdevHandleSet::NUM_WORDS) { this->num_ = fds_.max_handle_ + 1; return; } else { this->val_ = fds_.mask_.fds_bits[this->index_]; this->num_ = this->index_ * cdevHandleSet::WORD_SIZE; } } for (; BIT_DISABLED (this->val_); this->num_++) this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; #endif } cdevHandleSetIterator::cdevHandleSetIterator (cdevHandleSet &f) : fds_ (f), index_ (0), num_ (f.size_ == 0 ? f.max_handle_ + 1 : 0) { #ifndef _WIN32 for (; fds_.mask_.fds_bits[this->index_] == 0; this->index_++) this->num_ += cdevHandleSet::WORD_SIZE; for (this->val_ = this->fds_.mask_.fds_bits[this->index_]; (BIT_DISABLED (this->val_)) && this->num_ < cdevHandleSet::MAX_SIZE; this->num_++) this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; #endif } // ***************************************************************************** // * Synchronize the underlying FD_SET with the MAX_FD and the SIZE. // ***************************************************************************** void cdevHandleSet::sync (int max) { #ifndef _WIN32 this->size_ = 0; for (int i = max / cdevHandleSet::WORD_SIZE; i >= 0; i--) this->size_ += count_bits (this->mask_.fds_bits[i]); this->set_max (max); #endif } // ***************************************************************************** // * Resets the MAX_FD after a clear of the original MAX_FD. // ***************************************************************************** void cdevHandleSet::set_max (int current_max) { #ifndef _WIN32 int i = 0; if (this->size_ == 0) this->max_handle_ = -1; else { for (i = current_max / cdevHandleSet::WORD_SIZE; this->mask_.fds_bits[i] == 0; i--) ; this->max_handle_ = i * cdevHandleSet::WORD_SIZE; for (fd_mask val = this->mask_.fds_bits[i]; (val & ~1) != 0; val = (val >> 1) & cdevHandleSet::MSB_MASK) this->max_handle_++; } #endif } // ***************************************************************************** // * Debugging method that prints out the underlying mask. // ***************************************************************************** int cdevHandleSet::asciiDump (FILE * fp) { fprintf(fp, "[ "); for (int i = 0; i < this->max_handle_ + 1; i++) if (this->is_set (i)) fprintf(fp," %d ", i); fprintf(fp, " ]"); return this->size_; } void cdevHandleSet::reset (void) { this->max_handle_ = -1; this->size_ = 0; FD_ZERO (&this->mask_); } // ***************************************************************************** // * Constructor, initializes the bitmask to all 0s. // ***************************************************************************** cdevHandleSet::cdevHandleSet (void) { this->reset (); } cdevHandleSet::cdevHandleSet (const fd_set &fd_mask): size_ (0) { memcpy ((void *) &this->mask_, (void *) &fd_mask, sizeof this->mask_); // sync is empty for WIN32 this->sync (FD_SETSIZE); } // ***************************************************************************** // * Returns the number of the large bit. // ***************************************************************************** int cdevHandleSet::max_set (void) const { return this->max_handle_; } // ***************************************************************************** // * Checks whether FD is enabled. // ***************************************************************************** int cdevHandleSet::is_set (int fd) const { #ifdef _WIN32 return FD_ISSET ((SOCKET)fd, &this->mask_); #else return FD_ISSET (fd, &this->mask_); #endif } // ***************************************************************************** // * Enables the FD. // ***************************************************************************** void cdevHandleSet::set_bit (int fd) { if (!this->is_set (fd)) { #ifdef _WIN32 FD_SET ((SOCKET)fd, &this->mask_); #else FD_SET (fd, &this->mask_); this->size_++; // ***************************************************** // * again VMS system has different idea // ***************************************************** #if defined(__VMS) && defined(_TGV_MULTINET) if (FD_TO_BIT_OFFSET(fd) > this->max_handle_) this->max_handle_ = FD_TO_BIT_OFFSET(fd); #else if (fd > this->max_handle_) this->max_handle_ = fd; #endif #endif } } // ***************************************************************************** // * Disables the FD. // ***************************************************************************** void cdevHandleSet::clr_bit (int fd) { if (this->is_set (fd)) { #ifdef _WIN32 FD_CLR ((SOCKET)fd, &this->mask_); #else FD_CLR (fd, &this->mask_); this->size_--; #if defined(__VMS) && defined(_TGV_MULTINET) if (FD_TO_BIT_OFFSET(fd) == this->max_handle_) this->set_max (this->max_handle_); #else if (fd == this->max_handle_) this->set_max (this->max_handle_); #endif #endif } } // ***************************************************************************** // * Returns a count of the number of enabled bits. // ***************************************************************************** int cdevHandleSet::num_set (void) const { #ifdef _WIN32 return this->mask_.fd_count; #else return this->size_; #endif } int cdevHandleSetIterator::operator () (void) { #ifdef _WIN32 return this->index_ < this->fds_.mask_.fd_count ? fds_.mask_.fd_array[this->index_] : -1; #else #if defined(__VMS) && defined(_TGV_MULTINET) return FD_FROM_BIT_OFFSET(this->num_ <= this->fds_.max_handle_ ? this->num_ :-1); #else return this->num_ <= this->fds_.max_handle_ ? this->num_ : -1; #endif #endif }