Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Handle_Set.cpp
blob98d9ca5e9fa430872f239660d5bab1ae2f9e86ef
1 #include "ace/Handle_Set.h"
2 #if defined (ACE_HAS_ALLOC_HOOKS)
3 # include "ace/Malloc_Base.h"
4 #endif /* ACE_HAS_ALLOC_HOOKS */
6 #if !defined (__ACE_INLINE__)
7 #include "ace/Handle_Set.inl"
8 #endif /* __ACE_INLINE__ */
10 #include "ace/OS_NS_string.h"
12 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
14 ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set)
16 // ACE_MSB_MASK is only used here.
17 // This needs to go here to avoid overflow problems on some compilers.
18 #if defined (ACE_HANDLE_SET_USES_FD_ARRAY)
19 // Do we have an fd_mask?
20 # define ACE_MSB_MASK (~(1 << (NFDBITS - 1)))
21 #else /* ! ACE_HANDLE_SET_USES_FD_ARRAY */
22 # define ACE_MSB_MASK (~((fd_mask) 1 << (NFDBITS - 1)))
23 #endif /* ! ACE_HANDLE_SET_USES_FD_ARRAY */
25 #if defined (ACE_LINUX) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !defined (_XOPEN_SOURCE)
26 // XPG4.2 requires the fds_bits member name, so it is not enabled by
27 // default on Linux/glibc-2.1.x systems. Instead use "__fds_bits."
28 // Ugly, but "what are you going to do?" 8-)
29 #define fds_bits __fds_bits
30 #elif defined ACE_FDS_BITS
31 #define fds_bits ACE_FDS_BITS
32 #endif /* ACE_LINUX && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !_XOPEN_SOURCE */
34 void
35 ACE_Handle_Set::dump () const
37 #if defined (ACE_HAS_DUMP)
38 ACE_TRACE ("ACE_Handle_Set::dump");
40 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
42 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsize_ = %d"), this->size_));
43 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmax_handle_ = %d"), this->max_handle_));
44 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\n[ ")));
46 #if defined (ACE_HANDLE_SET_USES_FD_ARRAY)
47 for (size_t i = 0; i < (size_t) this->mask_.fd_count + 1; i++)
48 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT (" %x "), this->mask_.fd_array[i]));
49 #else /* !ACE_HANDLE_SET_USES_FD_ARRAY */
50 for (ACE_HANDLE i = 0; i < this->max_handle_ + 1; i++)
51 if (this->is_set (i))
52 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT (" %d "), i));
53 #endif /* ACE_HANDLE_SET_USES_FD_ARRAY */
55 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT (" ]\n")));
56 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
57 #endif /* ACE_HAS_DUMP */
60 // Table that maps bytes to counts of the enabled bits in each value
61 // from 0 to 255,
63 // nbits_[0] == 0
65 // because there are no bits enabled for the value 0.
67 // nbits_[5] == 2
69 // because there are 2 bits enabled in the value 5, i.e., it's
70 // 101 in binary.
72 const char ACE_Handle_Set::nbits_[256] =
74 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
75 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
76 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
77 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
78 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
79 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
80 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
81 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
82 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
83 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
84 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
85 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
86 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
87 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
88 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
89 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
91 // Constructor, initializes the bitmask to all 0s.
93 ACE_Handle_Set::ACE_Handle_Set ()
95 ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set");
96 this->reset ();
99 ACE_Handle_Set::ACE_Handle_Set (const fd_set &fd_mask)
101 ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set");
102 this->reset ();
103 ACE_OS::memcpy ((void *) &this->mask_,
104 (void *) &fd_mask,
105 sizeof this->mask_);
106 #if !defined (ACE_HANDLE_SET_USES_FD_ARRAY)
107 this->sync (ACE_Handle_Set::MAXSIZE);
108 #if defined (ACE_HAS_BIG_FD_SET)
109 this->min_handle_ = 0;
110 #endif /* ACE_HAS_BIG_FD_SET */
111 #endif /* !ACE_HANDLE_SET_USES_FD_ARRAY */
114 // Counts the number of bits enabled in N. Uses a table lookup to
115 // speed up the count.
118 ACE_Handle_Set::count_bits (u_long n)
120 ACE_TRACE ("ACE_Handle_Set::count_bits");
121 #if defined (ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT)
122 int rval = 0;
124 // Count the number of enabled bits in <n>. This algorithm is very
125 // fast, i.e., O(enabled bits in n).
127 for (u_long m = n;
128 m != 0;
129 m &= m - 1)
130 rval++;
132 return rval;
133 #else
134 return (ACE_Handle_Set::nbits_[n & 0xff]
135 + ACE_Handle_Set::nbits_[(n >> 8) & 0xff]
136 + ACE_Handle_Set::nbits_[(n >> 16) & 0xff]
137 + ACE_Handle_Set::nbits_[(n >> 24) & 0xff]);
138 #endif /* ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT */
141 #if defined (ACE_HAS_BIG_FD_SET)
142 // Find the bit position counting from right to left worst case
143 // (1<<31) is 8.
146 ACE_Handle_Set::bitpos (u_long bit)
148 int l = 0;
149 u_long n = bit - 1;
151 // This is a fast count method when have the most significative bit.
153 while (n >> 8)
155 n >>= 8;
156 l += 8;
159 // Is greater than 15?
160 if (n & 16)
162 n >>= 4;
163 l += 4;
166 // Count number remaining bits.
167 while (n != 0)
169 n &= n - 1;
170 l++;
172 return l;
174 #endif /* ACE_HAS_BIG_FD_SET */
176 // Synchronize the underlying FD_SET with the MAX_FD and the SIZE.
178 #if defined (ACE_USE_SHIFT_FOR_EFFICIENCY)
179 // These don't work because shifting right 3 bits is not the same as
180 // dividing by 3, e.g., dividing by 8 requires shifting right 3 bits.
181 // In order to do the shift, we need to calculate the number of bits
182 // at some point.
183 #define ACE_DIV_BY_WORDSIZE(x) ((x) >> ((int) ACE_Handle_Set::WORDSIZE))
184 #define ACE_MULT_BY_WORDSIZE(x) ((x) << ((int) ACE_Handle_Set::WORDSIZE))
185 #else
186 #define ACE_DIV_BY_WORDSIZE(x) ((x) / ((int) ACE_Handle_Set::WORDSIZE))
187 #define ACE_MULT_BY_WORDSIZE(x) ((x) * ((int) ACE_Handle_Set::WORDSIZE))
188 #endif /* ACE_USE_SHIFT_FOR_EFFICIENCY */
190 void
191 ACE_Handle_Set::sync (ACE_HANDLE max)
193 ACE_TRACE ("ACE_Handle_Set::sync");
194 #if !defined (ACE_HANDLE_SET_USES_FD_ARRAY)
195 fd_mask *maskp = (fd_mask *)(this->mask_.fds_bits);
196 this->size_ = 0;
198 for (int i = ACE_DIV_BY_WORDSIZE (max - 1);
199 i >= 0;
200 i--)
201 this->size_ += ACE_Handle_Set::count_bits (maskp[i]);
203 this->set_max (max);
204 #else
205 ACE_UNUSED_ARG (max);
206 #endif /* !ACE_HANDLE_SET_USES_FD_ARRAY */
209 // Resets the MAX_FD after a clear of the original MAX_FD.
211 void
212 ACE_Handle_Set::set_max (ACE_HANDLE current_max)
214 ACE_TRACE ("ACE_Handle_Set::set_max");
215 #if !defined(ACE_HANDLE_SET_USES_FD_ARRAY)
216 fd_mask * maskp = (fd_mask *)(this->mask_.fds_bits);
218 if (this->size_ == 0)
219 this->max_handle_ = ACE_INVALID_HANDLE;
220 else
222 int i;
224 for (i = ACE_DIV_BY_WORDSIZE (current_max - 1);
225 maskp[i] == 0;
226 i--)
227 continue;
228 this->max_handle_ = ACE_MULT_BY_WORDSIZE (i);
229 for (fd_mask val = maskp[i];
230 (val & ~1) != 0; // This obscure code is needed since "bit 0" is in location 1...
231 val = (val >> 1) & ACE_MSB_MASK)
232 ++this->max_handle_;
235 // Do some sanity checking...
236 if (this->max_handle_ >= ACE_Handle_Set::MAXSIZE)
237 this->max_handle_ = ACE_Handle_Set::MAXSIZE - 1;
238 #else
239 ACE_UNUSED_ARG (current_max);
240 #endif /* !ACE_HANDLE_SET_USES_FD_ARRAY */
243 ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set_Iterator)
245 void
246 ACE_Handle_Set_Iterator::dump () const
248 #if defined (ACE_HAS_DUMP)
249 ACE_TRACE ("ACE_Handle_Set_Iterator::dump");
251 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
252 #if defined(ACE_HANDLE_SET_USES_FD_ARRAY) || !defined(ACE_HAS_BIG_FD_SET)
253 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhandle_index_ = %d"), this->handle_index_));
254 #elif defined(ACE_HAS_BIG_FD_SET)
255 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_max_ = %d"), this->word_max_));
256 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_val_ = %d"), this->word_val_));
257 #endif
258 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nword_num_ = %d"), this->word_num_));
259 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
260 #endif /* ACE_HAS_DUMP */
263 ACE_HANDLE
264 ACE_Handle_Set_Iterator::operator () ()
266 ACE_TRACE ("ACE_Handle_Set_Iterator::operator");
267 #if defined (ACE_HANDLE_SET_USES_FD_ARRAY)
268 if (this->handle_index_ < this->handles_.mask_.fd_count)
269 // Return the handle and advance the iterator.
270 return (ACE_HANDLE) this->handles_.mask_.fd_array[this->handle_index_++];
271 else
272 return ACE_INVALID_HANDLE;
274 #elif !defined (ACE_HAS_BIG_FD_SET) /* !ACE_HANDLE_SET_USES_FD_ARRAY */
275 // No sense searching further than the max_handle_ + 1;
276 ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1;
278 // HP-UX 11 plays some games with the fd_mask type - fd_mask is
279 // defined as an int_32t, but the fds_bits is an array of longs.
280 // This makes plainly indexing through the array by hand tricky,
281 // since the FD_* macros treat the array as int32_t. So the bits
282 // are in the right place for int32_t, even though the array is
283 // long. This, they say, is to preserve the same in-memory layout
284 // for 32-bit and 64-bit processes. So, we play the same game as
285 // the FD_* macros to get the bits right. On all other systems,
286 // this amounts to practically a NOP, since this is what would have
287 // been done anyway, without all this type jazz.
288 fd_mask * maskp = (fd_mask *)(this->handles_.mask_.fds_bits);
290 if (this->handle_index_ >= maxhandlep1)
291 // We've seen all the handles we're interested in seeing for this
292 // iterator.
293 return ACE_INVALID_HANDLE;
294 else
296 ACE_HANDLE result = this->handle_index_;
298 // Increment the iterator and advance to the next bit in this
299 // word.
300 this->handle_index_++;
301 this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
303 // If we've examined all the bits in this word, we'll go onto
304 // the next word.
306 if (this->word_val_ == 0)
308 // Start the handle_index_ at the beginning of the next word
309 // and then loop until we've found the first non-zero bit or
310 // we run past the <maxhandlep1> of the bitset.
312 for (this->handle_index_ = ACE_MULT_BY_WORDSIZE(++this->word_num_);
313 this->handle_index_ < maxhandlep1
314 && maskp[this->word_num_] == 0;
315 this->word_num_++)
316 this->handle_index_ += ACE_Handle_Set::WORDSIZE;
318 // If the bit index becomes >= the maxhandlep1 that means
319 // there weren't any more bits set that we want to consider.
320 // Therefore, we'll just store the maxhandlep1, which will
321 // cause <operator()> to return <ACE_INVALID_HANDLE>
322 // immediately next time it's called.
323 if (this->handle_index_ >= maxhandlep1)
325 this->handle_index_ = maxhandlep1;
326 return result;
328 else
329 // Load the bits of the next word.
330 this->word_val_ = maskp[this->word_num_];
333 // Loop until we get <word_val_> to have its least significant
334 // bit enabled, keeping track of which <handle_index> this
335 // represents (this information is used by subsequent calls to
336 // <operator()>).
337 for (;
338 ACE_BIT_DISABLED (this->word_val_, 1);
339 this->handle_index_++)
340 this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
342 return result;
344 #else /* !ACE_HAS_BIG_FD_SET */
345 // Find the first word in fds_bits with bit on
346 u_long lsb = this->word_val_;
348 if (lsb == 0)
352 // We have exceeded the word count in Handle_Set?
353 if (++this->word_num_ >= this->word_max_)
354 return ACE_INVALID_HANDLE;
356 lsb = this->handles_.mask_.fds_bits[this->word_num_];
358 while (lsb == 0);
360 // Set index to word boundary.
361 this->handle_index_ = ACE_MULT_BY_WORDSIZE (this->word_num_);
363 // Put new word_val.
364 this->word_val_ = lsb;
366 // Find the least significative bit.
367 lsb &= ~(lsb - 1);
369 // Remove least significative bit.
370 this->word_val_ ^= lsb;
372 // Save to calculate bit distance.
373 this->oldlsb_ = lsb;
375 // Move index to least significative bit.
376 while (lsb >>= 1)
377 this->handle_index_++;
379 else
381 // Find the least significative bit.
382 lsb &= ~(lsb - 1);
384 // Remove least significative bit.
385 this->word_val_ ^= lsb;
387 u_long n = lsb - this->oldlsb_;
389 // Move index to bit distance between new lsb and old lsb.
392 this->handle_index_++;
393 n &= n >> 1;
395 while (n != 0);
397 this->oldlsb_ = lsb;
400 return this->handle_index_;
401 #endif /* ACE_HANDLE_SET_USES_FD_ARRAY */
404 ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs)
405 : handles_ (hs),
406 #if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_HANDLE_SET_USES_FD_ARRAY)
407 handle_index_ (0),
408 word_num_ (-1)
409 #elif defined (ACE_HAS_BIG_FD_SET)
410 handle_index_ (0),
411 oldlsb_ (0),
412 word_max_ (hs.max_handle_ == ACE_INVALID_HANDLE
414 : ((ACE_DIV_BY_WORDSIZE (hs.max_handle_)) + 1))
415 #endif /* ACE_HAS_BIG_FD_SET */
417 ACE_TRACE ("ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator");
418 #if !defined (ACE_HANDLE_SET_USES_FD_ARRAY) && !defined (ACE_HAS_BIG_FD_SET)
419 // No sense searching further than the max_handle_ + 1;
420 ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1;
422 fd_mask *maskp = (fd_mask *)(this->handles_.mask_.fds_bits);
424 // Loop until we've found the first non-zero bit or we run past the
425 // <maxhandlep1> of the bitset.
426 while (this->handle_index_ < maxhandlep1
427 && maskp[++this->word_num_] == 0)
428 this->handle_index_ += ACE_Handle_Set::WORDSIZE;
430 // If the bit index becomes >= the maxhandlep1 that means there
431 // weren't any bits set. Therefore, we'll just store the
432 // maxhandlep1, which will cause <operator()> to return
433 // <ACE_INVALID_HANDLE> immediately.
434 if (this->handle_index_ >= maxhandlep1)
435 this->handle_index_ = maxhandlep1;
436 else
437 // Loop until we get <word_val_> to have its least significant bit
438 // enabled, keeping track of which <handle_index> this represents
439 // (this information is used by <operator()>).
440 for (this->word_val_ = maskp[this->word_num_];
441 ACE_BIT_DISABLED (this->word_val_, 1)
442 && this->handle_index_ < maxhandlep1;
443 this->handle_index_++)
444 this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
445 #elif !defined (ACE_HANDLE_SET_USES_FD_ARRAY) && defined (ACE_HAS_BIG_FD_SET)
446 if (this->word_max_==0)
448 this->word_num_ = -1;
449 this->word_val_ = 0;
451 else
453 this->word_num_ = ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1;
454 this->word_val_ = 0;
456 #endif /* !ACE_HANDLE_SET_USES_FD_ARRAY && !ACE_HAS_BIG_FD_SET */
459 void
460 ACE_Handle_Set_Iterator::reset_state ()
462 ACE_TRACE ("ACE_Handle_Set_Iterator::reset_state");
464 #if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_HANDLE_SET_USES_FD_ARRAY)
465 this->handle_index_ = 0;
466 this->word_num_ = -1;
467 #elif defined (ACE_HAS_BIG_FD_SET)
468 this->oldlsb_ = 0;
469 this->word_max_ =
470 this->handles_.max_handle_ == ACE_INVALID_HANDLE ? 0
471 : ((ACE_DIV_BY_WORDSIZE (this->handles_.max_handle_)) + 1);
472 #endif /* ACE_HAS_BIG_FD_SET */
474 #if !defined (ACE_HANDLE_SET_USES_FD_ARRAY) && !defined (ACE_HAS_BIG_FD_SET)
475 // No sense searching further than the max_handle_ + 1;
476 ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1;
478 fd_mask *maskp = (fd_mask *)(this->handles_.mask_.fds_bits);
480 // Loop until we've found the first non-zero bit or we run past the
481 // <maxhandlep1> of the bitset.
482 while (this->handle_index_ < maxhandlep1
483 && maskp[++this->word_num_] == 0)
484 this->handle_index_ += ACE_Handle_Set::WORDSIZE;
486 // If the bit index becomes >= the maxhandlep1 that means there
487 // weren't any bits set. Therefore, we'll just store the
488 // maxhandlep1, which will cause <operator()> to return
489 // <ACE_INVALID_HANDLE> immediately.
490 if (this->handle_index_ >= maxhandlep1)
491 this->handle_index_ = maxhandlep1;
492 else
493 // Loop until we get <word_val_> to have its least significant bit
494 // enabled, keeping track of which <handle_index> this represents
495 // (this information is used by <operator()>).
496 for (this->word_val_ = maskp[this->word_num_];
497 ACE_BIT_DISABLED (this->word_val_, 1)
498 && this->handle_index_ < maxhandlep1;
499 this->handle_index_++)
500 this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK;
501 #elif !defined (ACE_HANDLE_SET_USES_FD_ARRAY) && defined (ACE_HAS_BIG_FD_SET)
502 if (this->word_max_==0)
504 this->word_num_ = -1;
505 this->word_val_ = 0;
507 else
509 this->word_num_ =
510 ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1;
511 this->word_val_ = 0;
513 #endif /* !ACE_HANDLE_SET_USES_FD_ARRAY && !ACE_HAS_BIG_FD_SET */
516 ACE_END_VERSIONED_NAMESPACE_DECL