diff options
Diffstat (limited to 'ACE/ace/Handle_Set.cpp')
-rw-r--r-- | ACE/ace/Handle_Set.cpp | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/ACE/ace/Handle_Set.cpp b/ACE/ace/Handle_Set.cpp new file mode 100644 index 00000000000..6528483e344 --- /dev/null +++ b/ACE/ace/Handle_Set.cpp @@ -0,0 +1,578 @@ +// Handle_Set.cpp +// $Id$ + +#include "ace/Handle_Set.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Handle_Set.inl" +#endif /* __ACE_INLINE__ */ + +#include "ace/OS_NS_string.h" + +ACE_RCSID(ace, Handle_Set, "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set) + + // ACE_MSB_MASK is only used here. + // This needs to go here to avoid overflow problems on some compilers. +#if defined (ACE_WIN32) + // Does ACE_WIN32 have an fd_mask? +# define ACE_MSB_MASK (~(1 << (NFDBITS - 1))) +#else /* ! ACE_WIN32 */ +# define ACE_MSB_MASK (~((fd_mask) 1 << (NFDBITS - 1))) +#endif /* ! ACE_WIN32 */ + +#if defined (__BORLANDC__) && !defined (ACE_WIN32) +// The Borland C++ compiler on Linux also doesn't have fds_bits, but has __fds_bits. +#define fds_bits __fds_bits +#endif + +#if defined (linux) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !defined (_XOPEN_SOURCE) + // XPG4.2 requires the fds_bits member name, so it is not enabled by + // default on Linux/glibc-2.1.x systems. Instead use "__fds_bits." + // Ugly, but "what are you going to do?" 8-) +#define fds_bits __fds_bits +#endif /* linux && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !_XOPEN_SOURCE */ + +void +ACE_Handle_Set::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Handle_Set::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize_ = %d"), this->size_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmax_handle_ = %d"), this->max_handle_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n[ "))); + +#if defined (ACE_WIN32) + for (size_t i = 0; i < (size_t) this->mask_.fd_count + 1; i++) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" %x "), this->mask_.fd_array[i])); +#else /* !ACE_WIN32 */ + for (ACE_HANDLE i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" %d "), i)); +#endif /* ACE_WIN32 */ + + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" ]\n"))); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_HAS_DUMP */ +} + +// Table that maps bytes to counts of the enabled bits in each value +// from 0 to 255, +// +// nbits_[0] == 0 +// +// because there are no bits enabled for the value 0. +// +// nbits_[5] == 2 +// +// because there are 2 bits enabled in the value 5, i.e., it's +// 101 in binary. + +const char ACE_Handle_Set::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}; + +// Constructor, initializes the bitmask to all 0s. + +ACE_Handle_Set::ACE_Handle_Set (void) +{ + ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set"); + this->reset (); +} + +ACE_Handle_Set::ACE_Handle_Set (const ACE_FD_SET_TYPE &fd_mask) +{ + ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set"); + this->reset (); + ACE_OS::memcpy ((void *) &this->mask_, + (void *) &fd_mask, + sizeof this->mask_); +#if !defined (ACE_WIN32) + this->sync (ACE_Handle_Set::MAXSIZE); +#if defined (ACE_HAS_BIG_FD_SET) + this->min_handle_ = 0; +#endif /* ACE_HAS_BIG_FD_SET */ +#endif /* !ACE_WIN32 */ +} + +// Counts the number of bits enabled in N. Uses a table lookup to +// speed up the count. + +int +ACE_Handle_Set::count_bits (u_long n) +{ + + ACE_TRACE ("ACE_Handle_Set::count_bits"); +#if defined (ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT) + register int rval = 0; + + // Count the number of enabled bits in <n>. This algorithm is very + // fast, i.e., O(enabled bits in n). + + for (register u_long m = n; + m != 0; + m &= m - 1) + rval++; + + return rval; +#else + return (ACE_Handle_Set::nbits_[n & 0xff] + + ACE_Handle_Set::nbits_[(n >> 8) & 0xff] + + ACE_Handle_Set::nbits_[(n >> 16) & 0xff] + + ACE_Handle_Set::nbits_[(n >> 24) & 0xff]); +#endif /* ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT */ +} + +#if defined (ACE_HAS_BIG_FD_SET) +// Find the bit position counting from right to left worst case +// (1<<31) is 8. + +int +ACE_Handle_Set::bitpos (u_long bit) +{ + register int l = 0; + register u_long n = bit - 1; + + // This is a fast count method when have the most significative bit. + + while (n >> 8) + { + n >>= 8; + l += 8; + } + + // Is greater than 15? + if (n & 16) + { + n >>= 4; + l += 4; + } + + // Count number remaining bits. + while (n != 0) + { + n &= n - 1; + l++; + } + return l; +} +#endif /* ACE_HAS_BIG_FD_SET */ + +// Synchronize the underlying FD_SET with the MAX_FD and the SIZE. + +#if defined (ACE_USE_SHIFT_FOR_EFFICIENCY) +// These don't work because shifting right 3 bits is not the same as +// dividing by 3, e.g., dividing by 8 requires shifting right 3 bits. +// In order to do the shift, we need to calculate the number of bits +// at some point. +#define ACE_DIV_BY_WORDSIZE(x) ((x) >> ((int) ACE_Handle_Set::WORDSIZE)) +#define ACE_MULT_BY_WORDSIZE(x) ((x) << ((int) ACE_Handle_Set::WORDSIZE)) +#else +#define ACE_DIV_BY_WORDSIZE(x) ((x) / ((int) ACE_Handle_Set::WORDSIZE)) +#define ACE_MULT_BY_WORDSIZE(x) ((x) * ((int) ACE_Handle_Set::WORDSIZE)) +#endif /* ACE_USE_SHIFT_FOR_EFFICIENCY */ + +void +ACE_Handle_Set::sync (ACE_HANDLE max) +{ + ACE_TRACE ("ACE_Handle_Set::sync"); +#if !defined (ACE_WIN32) + fd_mask *maskp = (fd_mask *)(this->mask_.fds_bits); + this->size_ = 0; + + for (int i = ACE_DIV_BY_WORDSIZE (max - 1); + i >= 0; + i--) + this->size_ += ACE_Handle_Set::count_bits (maskp[i]); + + this->set_max (max); +#else + ACE_UNUSED_ARG (max); +#endif /* !ACE_WIN32 */ +} + +// Resets the MAX_FD after a clear of the original MAX_FD. + +void +ACE_Handle_Set::set_max (ACE_HANDLE current_max) +{ + ACE_TRACE ("ACE_Handle_Set::set_max"); +#if !defined(ACE_WIN32) + fd_mask * maskp = (fd_mask *)(this->mask_.fds_bits); + + if (this->size_ == 0) + this->max_handle_ = ACE_INVALID_HANDLE; + else + { + int i; + + for (i = ACE_DIV_BY_WORDSIZE (current_max - 1); + maskp[i] == 0; + i--) + continue; +#if defined (ACE_TANDEM_NSK_BIT_ORDER) + // bits are in reverse order, MSB (sign bit) = bit 0. + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i); + for (fd_mask val = maskp[i]; + (val & ACE_MSB_MASK) != 0; + val = (val << 1)) + ++this->max_handle_; +#elif 1 /* !defined(ACE_HAS_BIG_FD_SET) */ + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i); + for (fd_mask val = maskp[i]; + (val & ~1) != 0; // This obscure code is needed since "bit 0" is in location 1... + val = (val >> 1) & ACE_MSB_MASK) + ++this->max_handle_; +#else + register u_long val = this->mask_.fds_bits[i]; + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i) + + ACE_Handle_Set::bitpos(val & ~(val - 1)); +#endif /* 1 */ + } + + // Do some sanity checking... + if (this->max_handle_ >= ACE_Handle_Set::MAXSIZE) + this->max_handle_ = ACE_Handle_Set::MAXSIZE - 1; +#else + ACE_UNUSED_ARG (current_max); +#endif /* !ACE_WIN32 */ +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set_Iterator) + +void +ACE_Handle_Set_Iterator::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Handle_Set_Iterator::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); +#if defined(ACE_WIN32) || !defined(ACE_HAS_BIG_FD_SET) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhandle_index_ = %d"), this->handle_index_)); +#elif defined(ACE_HAS_BIG_FD_SET) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_max_ = %d"), this->word_max_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_val_ = %d"), this->word_val_)); +#endif + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_num_ = %d"), this->word_num_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_HAS_DUMP */ +} + +ACE_HANDLE +ACE_Handle_Set_Iterator::operator () (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator"); +#if defined (ACE_WIN32) + if (this->handle_index_ < this->handles_.mask_.fd_count) + // Return the handle and advance the iterator. + return (ACE_HANDLE) this->handles_.mask_.fd_array[this->handle_index_++]; + else + return ACE_INVALID_HANDLE; + +#elif !defined (ACE_HAS_BIG_FD_SET) /* !ACE_WIN32 */ + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1; + + // HP-UX 11 plays some games with the fd_mask type - fd_mask is + // defined as an int_32t, but the fds_bits is an array of longs. + // This makes plainly indexing through the array by hand tricky, + // since the FD_* macros treat the array as int32_t. So the bits + // are in the right place for int32_t, even though the array is + // long. This, they say, is to preserve the same in-memory layout + // for 32-bit and 64-bit processes. So, we play the same game as + // the FD_* macros to get the bits right. On all other systems, + // this amounts to practically a NOP, since this is what would have + // been done anyway, without all this type jazz. + fd_mask * maskp = (fd_mask *)(this->handles_.mask_.fds_bits); + + if (this->handle_index_ >= maxhandlep1) + // We've seen all the handles we're interested in seeing for this + // iterator. + return ACE_INVALID_HANDLE; + else + { + ACE_HANDLE result = this->handle_index_; + + // Increment the iterator and advance to the next bit in this + // word. + this->handle_index_++; +#if defined (ACE_TANDEM_NSK_BIT_ORDER) + // bits are in reverse order, MSB (sign bit) = bit 0. + this->word_val_ = (this->word_val_ << 1); +# else + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_TANDEM_NSK_BIT_ORDER */ + + // If we've examined all the bits in this word, we'll go onto + // the next word. + + if (this->word_val_ == 0) + { + // Start the handle_index_ at the beginning of the next word + // and then loop until we've found the first non-zero bit or + // we run past the <maxhandlep1> of the bitset. + + for (this->handle_index_ = ACE_MULT_BY_WORDSIZE(++this->word_num_); + this->handle_index_ < maxhandlep1 + && maskp[this->word_num_] == 0; + this->word_num_++) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means + // there weren't any more bits set that we want to consider. + // Therefore, we'll just store the maxhandlep1, which will + // cause <operator()> to return <ACE_INVALID_HANDLE> + // immediately next time it's called. + if (this->handle_index_ >= maxhandlep1) + { + this->handle_index_ = maxhandlep1; + return result; + } + else + // Load the bits of the next word. + this->word_val_ = maskp[this->word_num_]; + } + + // Loop until we get <word_val_> to have its least significant + // bit enabled, keeping track of which <handle_index> this + // represents (this information is used by subsequent calls to + // <operator()>). + +#if defined (ACE_TANDEM_NSK_BIT_ORDER) + // bits are in reverse order, MSB (sign bit) = bit 0. + for (; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (; + ACE_BIT_DISABLED (this->word_val_, 1); + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_TANDEM_NSK_BIT_ORDER */ + + return result; + } +#else /* !ACE_HAS_BIG_FD_SET */ + // Find the first word in fds_bits with bit on + register u_long lsb = this->word_val_; + + if (lsb == 0) + { + do + { + // We have exceeded the word count in Handle_Set? + if (++this->word_num_ >= this->word_max_) + return ACE_INVALID_HANDLE; + + lsb = this->handles_.mask_.fds_bits[this->word_num_]; + } + while (lsb == 0); + + // Set index to word boundary. + this->handle_index_ = ACE_MULT_BY_WORDSIZE (this->word_num_); + + // Put new word_val. + this->word_val_ = lsb; + + // Find the least significative bit. + lsb &= ~(lsb - 1); + + // Remove least significative bit. + this->word_val_ ^= lsb; + + // Save to calculate bit distance. + this->oldlsb_ = lsb; + + // Move index to least significative bit. + while (lsb >>= 1) + this->handle_index_++; + } + else + { + // Find the least significative bit. + lsb &= ~(lsb - 1); + + // Remove least significative bit. + this->word_val_ ^= lsb; + + register u_long n = lsb - this->oldlsb_; + + // Move index to bit distance between new lsb and old lsb. + do + { + this->handle_index_++; + n &= n >> 1; + } + while (n != 0); + + this->oldlsb_ = lsb; + } + + return this->handle_index_; +#endif /* ACE_WIN32 */ +} + +void +ACE_Handle_Set_Iterator::operator++ (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator++"); + + // This is now a no-op. +} + +ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs) + : handles_ (hs), +#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32) + handle_index_ (0), + word_num_ (-1) +#elif defined (ACE_HAS_BIG_FD_SET) + oldlsb_ (0), + word_max_ (hs.max_handle_ == ACE_INVALID_HANDLE + ? 0 + : ((ACE_DIV_BY_WORDSIZE (hs.max_handle_)) + 1)) +#endif /* ACE_HAS_BIG_FD_SET */ +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator"); +#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET) + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = + this->handles_.max_handle_ + 1; + + fd_mask *maskp = + (fd_mask *)(this->handles_.mask_.fds_bits); + + // Loop until we've found the first non-zero bit or we run past the + // <maxhandlep1> of the bitset. + while (this->handle_index_ < maxhandlep1 + && maskp[++this->word_num_] == 0) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means there + // weren't any bits set. Therefore, we'll just store the + // maxhandlep1, which will cause <operator()> to return + // <ACE_INVALID_HANDLE> immediately. + if (this->handle_index_ >= maxhandlep1) + this->handle_index_ = maxhandlep1; + else + // Loop until we get <word_val_> to have its least significant bit + // enabled, keeping track of which <handle_index> this represents + // (this information is used by <operator()>). +#if defined (ACE_TANDEM_NSK_BIT_ORDER) + // bits are in reverse order, MSB (sign bit) = bit 0. + for (this->word_val_ = maskp[this->word_num_]; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (this->word_val_ = maskp[this->word_num_]; + ACE_BIT_DISABLED (this->word_val_, 1) + && this->handle_index_ < maxhandlep1; + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_TANDEM_NSK_BIT_ORDER */ +#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET) + if (this->word_max_==0) + { + this->word_num_ = -1; + this->word_val_ = 0; + } + else + { + this->word_num_ = + ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1; + this->word_val_ = 0; + } +#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */ +} + + +void +ACE_Handle_Set_Iterator::reset_state (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::reset_state"); + +#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32) + this->handle_index_ = 0; + this->word_num_ = -1; +#elif defined (ACE_HAS_BIG_FD_SET) + this->oldlsb_ = 0; + this->word_max_ = + this->handles_.max_handle_ == ACE_INVALID_HANDLE ? 0 + : ((ACE_DIV_BY_WORDSIZE (this->handles_.max_handle_)) + 1); +#endif /* ACE_HAS_BIG_FD_SET */ + +#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET) + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = + this->handles_.max_handle_ + 1; + + fd_mask *maskp = + (fd_mask *)(this->handles_.mask_.fds_bits); + + // Loop until we've found the first non-zero bit or we run past the + // <maxhandlep1> of the bitset. + while (this->handle_index_ < maxhandlep1 + && maskp[++this->word_num_] == 0) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means there + // weren't any bits set. Therefore, we'll just store the + // maxhandlep1, which will cause <operator()> to return + // <ACE_INVALID_HANDLE> immediately. + if (this->handle_index_ >= maxhandlep1) + this->handle_index_ = maxhandlep1; + else + // Loop until we get <word_val_> to have its least significant bit + // enabled, keeping track of which <handle_index> this represents + // (this information is used by <operator()>). +#if defined (ACE_TANDEM_NSK_BIT_ORDER) + // bits are in reverse order, MSB (sign bit) = bit 0. + for (this->word_val_ = maskp[this->word_num_]; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (this->word_val_ = maskp[this->word_num_]; + ACE_BIT_DISABLED (this->word_val_, 1) + && this->handle_index_ < maxhandlep1; + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_TANDEM_NSK_BIT_ORDER */ +#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET) + if (this->word_max_==0) + { + this->word_num_ = -1; + this->word_val_ = 0; + } + else + { + this->word_num_ = + ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1; + this->word_val_ = 0; + } +#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */ +} + +ACE_END_VERSIONED_NAMESPACE_DECL |