Main Page Class Hierarchy Alphabetical List Compound List File List Compound Members File Members

# TAO_ESF_Proxy_Collection Class Template Reference

ESF_Proxy_Collection. More...

`#include <ESF_Proxy_Collection.h>`

Inheritance diagram for TAO_ESF_Proxy_Collection:

[legend]
List of all members.

## Public Methods
virtual | ~TAO_ESF_Proxy_Collection (void)
| destructor. More...
virtual void | for_each (TAO_ESF_Worker< PROXY > *worker ACE_ENV_ARG_DECL)=0
| Iterate over the collection and invoke worker->work() for each member of the collection. More...
virtual void | connected (PROXY *proxy ACE_ENV_ARG_DECL)=0
| Insert a new element into the collection. The collection assumes ownership of the element. More...
virtual void | reconnected (PROXY *proxy ACE_ENV_ARG_DECL)=0
| Insert an element into the collection. More...
virtual void | disconnected (PROXY *proxy ACE_ENV_ARG_DECL)=0
| Remove an element from the collection. More...
virtual void | shutdown (ACE_ENV_SINGLE_ARG_DECL)=0
| The EC is shutting down, must release all the elements. More...

## Detailed Description

### template<class PROXY>
class TAO_ESF_Proxy_Collection< PROXY >

ESF_Proxy_Collection.

Many components in an Event Service need to keep a collection of proxies; these collections must be able to cope with several concurrency issues: + Some threads may need to iterate over the collection and invoke a method on each element. Locking the collection while this is done is not feasible in all cases: under some configurations the same thread that is iterating over the collection may need to make changes to the set. + A recursive lock does not solve the concurrency problems because recursive changes to the collection still invalidate the iterators.

There are several solutions to this problem (see the VARIANTS) section, and there is no single one that works bests in all cases. As usual, we wish the strategize the protocol used to serialize iterations and changes to the collection. This class encapsulates that protocol.

The usual form of the Iterator pattern does not work well in this case: in several variants the synchronization protocol and the iteration loop must collaborate to work efficiently. Exposing an external iterator would require that every other component in the system can support all the synchronization protocols. It is possible to hide some of that complexity using heavy weight iterators, but their use is ackward, specially since the Koening-style iterators have become more popular.

Regular member functions are used to insert, remove and update members of the collection and to shutdown (i.e. perform final cleanup operations).

The class must also collaborate with other components of the EC to efficiently and safely perform memory managment of the members in the collection.

The PROXY object must be reference counted with the following operations:

+ _incr_refcnt() - increment the reference count. + _decr_refcnt() - decrement the reference count.

= VARIANTS

We identify several sources of variation:

+ Immediate_Changes: in this variant the iteration in performed while holding some kind of synchronization primitive, such as a thread mutex, a recursive mutex, a RW lock, etc. This is only useful in configurations where a separate thread dispatches the events, and thus, can only be used with real locks. + Copy_On_Read: before performing the iteration the collection is duplicated into a temporary array. Thus no locks are held during the iteration. This is a very expensive approach, but useful in many cases. The kind of lock is also strategized in this case. + Copy_On_Write: this is very similar to the previous approach, but the collection is only duplicated when a change is required while some thread is performing an iteration. The iteration continues over the original copy, while the changes are performed in the duplicate. The new copy of the collection is used for any subsequent operations, the original is discarded when the last thread using it completes its work. This approach optimizes for the case where no changes are is duplicated into a temporary array. Thus no locks are held during the iteration. This is a very expensive approach, but useful in many cases. The kind of lock is also strategized in this case. + Delayed_Changes: before starting the iteration a counter is incremented, this counter is used to keep track of the number of threads concurrently using the collection. If a thread wants to perform a change to the collection it must first verify that there are no threads iterating over it. If there are any threads then the thread queues the modification for later execution, using the Command pattern. The kind of lock is strategized, as this approach is used in single threaded configurations. There are two main variations:

- An upcall can result in new dispatches: in this case we have to keep track of a the list of current threads using a Set, to avoid dead-locks. The design is not complete, probably similar to the next one.
- Otherwise we just need to control the concurrency using the algorithm described below.

It assumes ownership of the proxies added to the collection, it increases the reference count.

Locking is provided by derived classes.

## Constructor & Destructor Documentation

template<class PROXY>
TAO_ESF_Proxy_Collection< PROXY >::~TAO_ESF_Proxy_Collection | ( | void |  | ) | `[virtual]`

| destructor.

## Member Function Documentation

template<class PROXY>
virtual void TAO_ESF_Proxy_Collection< PROXY >::connected | ( | PROXY *proxy | ACE_ENV_ARG_DECL | ) | `[pure virtual]`

| Insert a new element into the collection. The collection assumes ownership of the element. Reimplemented in TAO_ESF_Copy_On_Read, TAO_ESF_Copy_On_Write, TAO_ESF_Delayed_Changes, TAO_ESF_Immediate_Changes, and TAO_ESF_Delayed_Changes< PROXY, COLLECTION, ITERATOR, ACE_SYNCH_USE >.

template<class PROXY>
virtual void TAO_ESF_Proxy_Collection< PROXY >::disconnected | ( | PROXY *proxy | ACE_ENV_ARG_DECL | ) | `[pure virtual]`

| Remove an element from the collection. Reimplemented in TAO_ESF_Copy_On_Read, TAO_ESF_Copy_On_Write, TAO_ESF_Delayed_Changes, TAO_ESF_Immediate_Changes, and TAO_ESF_Delayed_Changes< PROXY, COLLECTION, ITERATOR, ACE_SYNCH_USE >.

template<class PROXY>
virtual void TAO_ESF_Proxy_Collection< PROXY >::for_each | ( | TAO_ESF_Worker< PROXY > *worker | ACE_ENV_ARG_DECL | ) | `[pure virtual]`

| Iterate over the collection and invoke worker->work() for each member of the collection. This encapsulates Reimplemented in TAO_ESF_Copy_On_Read, TAO_ESF_Copy_On_Write, TAO_ESF_Delayed_Changes, TAO_ESF_Immediate_Changes, and TAO_ESF_Delayed_Changes< PROXY, COLLECTION, ITERATOR, ACE_SYNCH_USE >.

template<class PROXY>
virtual void TAO_ESF_Proxy_Collection< PROXY >::reconnected | ( | PROXY *proxy | ACE_ENV_ARG_DECL | ) | `[pure virtual]`

| Insert an element into the collection. No errors can be raised if the element is already present. The collection assumes ownership, i.e. must invoke <proxy->_decr_refcnt()> if the element is already present in the collection. Reimplemented in TAO_ESF_Copy_On_Read, TAO_ESF_Copy_On_Write, TAO_ESF_Delayed_Changes, TAO_ESF_Immediate_Changes, and TAO_ESF_Delayed_Changes< PROXY, COLLECTION, ITERATOR, ACE_SYNCH_USE >.

template<class PROXY>
virtual void TAO_ESF_Proxy_Collection< PROXY >::shutdown | ( | ACE_ENV_SINGLE_ARG_DECL |  | ) | `[pure virtual]`

| The EC is shutting down, must release all the elements. Reimplemented in TAO_ESF_Copy_On_Read, TAO_ESF_Copy_On_Write, TAO_ESF_Delayed_Changes, TAO_ESF_Immediate_Changes, and TAO_ESF_Delayed_Changes< PROXY, COLLECTION, ITERATOR, ACE_SYNCH_USE >.

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

- ESF_Proxy_Collection.h
- ESF_Proxy_Collection.cpp