summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h')
-rw-r--r--TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h b/TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h
new file mode 100644
index 00000000000..9f69b025d41
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h
@@ -0,0 +1,184 @@
+/* -*- C++ -*- */
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// ORBSVCS Event Service Framework
+//
+// = FILENAME
+// ESF_Proxy_Collection
+//
+// = AUTHOR
+// Carlos O'Ryan (coryan@cs.wustl.edu)
+//
+// = CREDITS
+// http://www.cs.wustl.edu/~coryan/EC/index.html
+//
+// ============================================================================
+
+#ifndef TAO_ESF_PROXY_COLLECTION_H
+#define TAO_ESF_PROXY_COLLECTION_H
+
+#include "tao/corba.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+template<class Target> class TAO_ESF_Worker;
+
+template<class PROXY>
+class TAO_ESF_Proxy_Collection
+{
+ // = TITLE
+ // ESF_Proxy_Collection
+ //
+ // = DESCRIPTION
+ // 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.
+ //
+ // = REQUIREMENTS
+ // 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.
+ // IMPLEMENTATION: the design is not complete, probably
+ // similar to the next one.
+ // - Otherwise we just need to control the concurrency using the
+ // algorithm described below.
+ //
+ //
+ // = MEMORY MANAGMENT
+ // It assumes ownership of the proxies added to the collection,
+ // it increases the reference count.
+ //
+ // = LOCKING
+ // Locking is provided by derived classes.
+ //
+ // = TODO
+ //
+public:
+ virtual ~TAO_ESF_Proxy_Collection (void);
+ // destructor
+
+ virtual void for_each (TAO_ESF_Worker<PROXY> *worker,
+ CORBA::Environment &ACE_TRY_ENV) = 0;
+ // Iterate over the collection and invoke worker->work() for each
+ // member of the collection.
+ // This encapsulates
+
+ virtual void connected (PROXY *proxy,
+ CORBA::Environment &ACE_TRY_ENV) = 0;
+ // Insert a new element into the collection. The collection assumes
+ // ownership of the element.
+
+ virtual void reconnected (PROXY *proxy,
+ CORBA::Environment &ACE_TRY_ENV) = 0;
+ // 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.
+
+ virtual void disconnected (PROXY *proxy,
+ CORBA::Environment &ACE_TRY_ENV) = 0;
+ // Remove an element from the collection.
+
+ virtual void shutdown (CORBA::Environment &ACE_TRY_ENV) = 0;
+ // The EC is shutting down, must release all the elements.
+};
+
+// ****************************************************************
+
+#if defined (__ACE_INLINE__)
+#include "ESF_Proxy_Collection.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ESF_Proxy_Collection.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("ESF_Proxy_Collection.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* TAO_ESF_PROXY_COLLECTION_H */