Files
2022-12-13 12:44:04 +01:00

305 lines
9.4 KiB
C++

//-----------------------------------------------------------------------------
// 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
}