ONPOSIX  2.0
 All Classes Namespaces Files Functions Variables Enumerator Friends Macros Pages
DescriptorsMonitor Class Reference

Class to watch a set of descriptors and notify related classes. More...

#include <DescriptorsMonitor.hpp>

Classes

struct  monitoredDescriptor
 Association between a reader and a monitored descriptor. More...

Public Member Functions

 DescriptorsMonitor ()
 Constructor. It just initializes the set of descriptors.
virtual ~DescriptorsMonitor ()
 Destructor.
bool startMonitoringDescriptor (AbstractDescriptorReader &reader, PosixDescriptor &descriptor)
 Method to start monitoring a descriptor.
bool stopMonitoringDescriptor (PosixDescriptor &descriptor)
 Method to stop monitoring a descriptor.
bool wait ()
 Method to wait until some descriptor becomes ready for read operations.

Private Attributes

fd_set descriptorSet_
 Current set of monitored descriptors.
int highestDescriptor_
 Highest-value descriptor in descriptorSet_.
std::vector
< monitoredDescriptor * > 
descriptors_
 Associations between readers and monitored descriptors.

Detailed Description

Class to watch a set of descriptors and notify related classes.

This class implements the "Observer" design pattern, and allows classes inherited from AbstractDescriptorReader to be notified when a descriptor they monitor becomes ready for read operations. The class is a wrapper for the select() POSIX system call, so the descriptor may refer to both a file or a socket. When the descriptor becomes ready, this class notifies the reader class by calling AbstractDescriptorReader::dataAvailable(int descriptor). Notes:

  • This monitor works only for read operations (i.e., it does not monitor write operations or system exceptions) even if it can be easily extended to support also write operations.
  • One descriptor can be monitored by at most one receiver.
  • A receiver can monitor more than one descriptor.

It is not implemented as a Singleton because it must be possible to have more than one monitor with different sets of descriptors. Classes that want to make use of this class must inherit from virtual class AbstractDescriptorReader, because the readiness of the descriptor is notified through a call to AbstractDescriptorReader::dataAvailable(int descriptor).

Definition at line 62 of file DescriptorsMonitor.hpp.

Constructor & Destructor Documentation

Constructor. It just initializes the set of descriptors.

Definition at line 32 of file DescriptorsMonitor.cpp.

{
FD_ZERO(&descriptorSet_);
}
~DescriptorsMonitor ( )
virtual

Destructor.

It just deletes the data structure containing the association between readers and monitored descriptors. Note: it does not deletes the descriptors and the readers, because they are just pointers to classes allocated somewhere else.

Definition at line 45 of file DescriptorsMonitor.cpp.

{
for (std::vector<monitoredDescriptor*>::iterator i = descriptors_.begin();
i != descriptors_.end(); ++i)
delete(*i);
}

Member Function Documentation

bool startMonitoringDescriptor ( AbstractDescriptorReader reader,
PosixDescriptor descriptor 
)

Method to start monitoring a descriptor.

It is called by each class AbstractDescriptorReader that wants to be notified about a specific descriptor.

Parameters
readerclass that wants to be notified
descriptordescriptor
Returns
true in case of success; false if the descriptor is already monitored

Definition at line 61 of file DescriptorsMonitor.cpp.

{
if (FD_ISSET(descriptor.getDescriptorNumber(), &descriptorSet_)){
ERROR("Descriptor already monitored by some reader");
return false;
}
monitoredDescriptor* n = new monitoredDescriptor;
n->descriptor_ = &descriptor;
n->reader_ = &reader;
descriptors_.push_back(n);
FD_SET(descriptor.getDescriptorNumber(), &descriptorSet_);
if (highestDescriptor_ < descriptor.getDescriptorNumber())
highestDescriptor_ = descriptor.getDescriptorNumber();
return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool stopMonitoringDescriptor ( PosixDescriptor descriptor)

Method to stop monitoring a descriptor.

It is called by each class AbstractDescriptorReader that wants to stop notifications about a specific descriptor. The AbstractDescriptorReader class is not among arguments, because each descriptor can be monitored by at most one class.

Parameters
descriptorwhose notifications must be stopped
Returns
true in case of success; false if the descriptor was not monitored

Definition at line 90 of file DescriptorsMonitor.cpp.

{
if (!FD_ISSET(descriptor.getDescriptorNumber(), &descriptorSet_)){
ERROR("Descriptor was not monitored");
return false;
}
for (std::vector<monitoredDescriptor*>::iterator i = descriptors_.begin();
i != descriptors_.end(); ++i)
if ((*i)->descriptor_->getDescriptorNumber() ==
descriptor.getDescriptorNumber()) {
delete(*i);
descriptors_.erase(i);
break;
}
FD_CLR(descriptor.getDescriptorNumber(), &descriptorSet_);
return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool wait ( )

Method to wait until some descriptor becomes ready for read operations.

It suspends the execution of the program until a descriptor becomes ready.

Returns
true in case of success; false if selects() returns error

Definition at line 117 of file DescriptorsMonitor.cpp.

{
// Additional variable needed because select() will change the set
fd_set fd = descriptorSet_;
// We need this additional variable, because this method calls
// AbstractDescriptorReader::dataAvailable() which in turn can call
// DescriptorsMonitor::startMonitoringDescriptor() to start
// monitoring a further descriptor. This adds new descriptors to
// descriptors_ within the execution of this method, messing up things.
std::vector<monitoredDescriptor*> checkedDescriptors = descriptors_;
int ret = select(highestDescriptor_+1,
&fd,
NULL,
NULL,
NULL);
DEBUG("Select returned!");
if (ret == -1){
// Error in select()
ERROR("select()");
return false;
} else if (!ret) {
// Timeout
DEBUG("Timeout()");
return false;
} else {
// At least one descriptor is ready for read operations
for (std::vector<monitoredDescriptor*>::iterator i =
checkedDescriptors.begin();
i != checkedDescriptors.end(); ++i) {
if (FD_ISSET((*i)->descriptor_->getDescriptorNumber(),
&fd)) {
// Notify the class
DEBUG("Notifying class...");
((*i)->reader_)->dataAvailable(*((*i)->descriptor_));
}
}
return true;
}
}

Member Data Documentation

std::vector<monitoredDescriptor*> descriptors_
private

Associations between readers and monitored descriptors.

Definition at line 98 of file DescriptorsMonitor.hpp.

fd_set descriptorSet_
private

Current set of monitored descriptors.

This set is given as argument to the select() syscall.

Definition at line 68 of file DescriptorsMonitor.hpp.

int highestDescriptor_
private

Highest-value descriptor in descriptorSet_.

The select() syscall needs this value + 1.

Definition at line 75 of file DescriptorsMonitor.hpp.


The documentation for this class was generated from the following files: