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.h170
1 files changed, 170 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..86ed4f5bf86
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/ESF/ESF_Proxy_Collection.h
@@ -0,0 +1,170 @@
+// -*- C++ -*-
+
+/**
+ * @file ESF_Proxy_Collection.h
+ *
+ * $Id$
+ *
+ * @author Carlos O'Ryan (coryan@cs.wustl.edu)
+ *
+ * http://doc.ece.uci.edu/~coryan/EC/index.html
+ */
+
+#ifndef TAO_ESF_PROXY_COLLECTION_H
+#define TAO_ESF_PROXY_COLLECTION_H
+#include /**/ "ace/pre.h"
+
+#include "ace/CORBA_macros.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<class Target> class TAO_ESF_Worker;
+
+/**
+ * @class TAO_ESF_Proxy_Collection
+ *
+ * @brief 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.
+ */
+template<class PROXY>
+class TAO_ESF_Proxy_Collection
+{
+public:
+ /// destructor
+ virtual ~TAO_ESF_Proxy_Collection (void);
+
+ /**
+ * Iterate over the collection and invoke worker->work() for each
+ * member of the collection.
+ * This encapsulates
+ */
+ virtual void for_each (TAO_ESF_Worker<PROXY> *worker) = 0;
+
+ /// Insert a new element into the collection. The collection assumes
+ /// ownership of the element.
+ virtual void connected (PROXY *proxy) = 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 reconnected (PROXY *proxy) = 0;
+
+ /// Remove an element from the collection.
+ virtual void disconnected (PROXY *proxy) = 0;
+
+ /// The EC is shutting down, must release all the elements.
+ virtual void shutdown (void) = 0;
+};
+
+// ****************************************************************
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "orbsvcs/ESF/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 */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_ESF_PROXY_COLLECTION_H */