summaryrefslogtreecommitdiff
path: root/TAO/tao/Leader_Follower.h
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/Leader_Follower.h')
-rw-r--r--TAO/tao/Leader_Follower.h212
1 files changed, 124 insertions, 88 deletions
diff --git a/TAO/tao/Leader_Follower.h b/TAO/tao/Leader_Follower.h
index 2ff165ca020..2d3b6ae5360 100644
--- a/TAO/tao/Leader_Follower.h
+++ b/TAO/tao/Leader_Follower.h
@@ -13,16 +13,12 @@
#define TAO_LEADER_FOLLOWER_H
#include "ace/pre.h"
-#include "tao/LF_Follower.h"
#include "tao/ORB_Core.h"
-#include "ace/Intrusive_List.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
-class TAO_LF_Event;
-
class TAO_Export TAO_Leader_Follower
{
public:
@@ -53,22 +49,6 @@ public:
/// A server thread has finished is making a request.
void reset_client_thread (void);
- /// Wait on the Leader/Followers loop until one event happens.
- /**
- * @param event The event we wait for, the loop iterates until the
- * event is sucessful, or it fails due to timeout, and error or a
- * connection closed.
- * @param transport The transport attached to the event
- * @param max_wait_time Limit the time spent on the loop
- *
- * @todo Document this better, split the Follower code to the
- * TAO_LF_Follower class, we probably don't need the transport
- * object.
- */
- int wait_for_event (TAO_LF_Event *event,
- TAO_Transport *transport,
- ACE_Time_Value *max_wait_time);
-
/// The current thread has become the leader thread in the
/// client side leader-follower set.
void set_client_leader_thread (void) ;
@@ -91,62 +71,39 @@ public:
*/
int elect_new_leader (void);
- /** @name Follower creation/destructions
- *
- * The Leader/Followers set acts as a factory for the Follower
- * objects. Followers are used to represent a thread blocked
- * waiting in the Follower set.
- *
- * The Leader/Followers abstraction keeps a list of the waiting
- * followers, so it can wake up one when the leader thread stops
- * handling events.
- *
- * For performance reasons the Leader/Followers set uses a pool (or
- * free-list) to keep Follower objects unattached to any thread. It
- * could be tempting to use TSS to keep such followers, after all a
- * thread can only need one such Follower object, however, that does
- * not work with multiple Leader/Followers sets, consult this bug
- * report for more details:
- *
- * http://ace.cs.wustl.edu/bugzilla/show_bug.cgi?id=296
- *
- */
- //@{
- /// Allocate a new follower to the caller.
- TAO_LF_Follower *allocate_follower (void);
-
- /// The caller has finished using a follower.
- void release_follower (TAO_LF_Follower *);
- //@}
-
- /** @name Follower Set Operations
- *
- */
- //@{
- /// Add a new follower to the set
- void add_follower (TAO_LF_Follower *follower);
+ /// Node structure for the queue of followers
+ struct TAO_Export TAO_Follower_Node
+ {
+ /// Constructor
+ TAO_Follower_Node (TAO_SYNCH_CONDITION* follower_ptr);
- /// Removes a follower from the leader-follower set
- void remove_follower (TAO_LF_Follower *follower);
+ /// Follower
+ TAO_SYNCH_CONDITION *follower_;
- /// Checks if there are any followers available
+ /// Pointer to the next follower
+ TAO_Follower_Node *next_;
+ };
/**
- * @return 1 if there follower set is not empty
+ * adds the a follower to the set of followers in the leader-
+ * follower model
+ * returns 0 on success, -1 on failure.
*/
+ int add_follower (TAO_Follower_Node *follower_ptr);
+
+ /// checks for the availablity of a follower
+ /// returns 1 on available, 0 else
int follower_available (void) const;
- //@}
+ /// removes a follower from the leader-follower set
+ /// returns 0 on success, -1 on failure
+ int remove_follower (TAO_Follower_Node *follower_ptr);
- /// Get a reference to the underlying mutex
- TAO_SYNCH_MUTEX &lock (void);
+ /// returns randomly a follower from the leader-follower set
+ /// returns follower on success, else 0
+ TAO_SYNCH_CONDITION *get_next_follower (void);
- /// Provide a pre-initialized reverse lock for the Leader/Followers
- /// set.
- /**
- * The Leader/Followers set mutex must be release during some long
- * running operations. This helper class simplifies the process of
- * releasing and reacquiring said mutex.
- */
+ /// Accessors
+ TAO_SYNCH_MUTEX &lock (void);
ACE_Reverse_Lock<TAO_SYNCH_MUTEX> &reverse_lock (void);
/// Check if there are any client threads running
@@ -169,21 +126,6 @@ private:
*/
void reset_event_loop_thread_i (TAO_ORB_Core_TSS_Resources *tss);
- /** @name Follower Set Operations
- *
- */
- //@{
- /// Remote a follower from the Followers set and promote it to the
- /// leader role.
- /**
- * This is a helper routine for elect_new_leader(), after verifying
- * that all the pre-conditions are satisfied the Follower set is
- * changed and the promoted Follower is signaled.
- */
- int elect_new_leader_i (void);
-
- //@}
-
private:
/// The orb core
TAO_ORB_Core *orb_core_;
@@ -194,12 +136,32 @@ private:
/// do protect the access to the following three members
ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock_;
- /// Implement the Leader/Followers set using an intrusive list
- typedef ACE_Intrusive_List<TAO_LF_Follower> Follower_Set;
- Follower_Set follower_set_;
+ /// Queue to store the followers.
+ struct TAO_Export TAO_Follower_Queue
+ {
+ /// Constructor
+ TAO_Follower_Queue (void);
+
+ /// Checks if the queue is empty.
+ int is_empty (void) const;
+
+ /// Removes a follower from the queue.
+ int remove (TAO_Follower_Node *);
- /// Use a free list to allocate and release Follower objects
- Follower_Set follower_free_list_;
+ /// Inserts a follower into the queue.
+ /// Returns 0 on success, -1 for failure, 1 if the element is already
+ /// present.
+ int insert (TAO_Follower_Node *);
+
+ /// Pointer to the head of the queue.
+ TAO_Follower_Node *head_;
+
+ /// Pointer to the tail of the queue.
+ TAO_Follower_Node *tail_;
+ };
+
+ /// Queue to keep the followers on the stack.
+ TAO_Follower_Queue follower_set_;
/**
* Count the number of active leaders.
@@ -255,6 +217,80 @@ private:
TAO_Leader_Follower &leader_follower_;
};
+class TAO_LF_Strategy;
+
+class TAO_Export TAO_LF_Event_Loop_Thread_Helper
+{
+public:
+ /// Constructor
+ TAO_LF_Event_Loop_Thread_Helper (TAO_Leader_Follower &leader_follower,
+ TAO_LF_Strategy &lf_strategy);
+
+ /// Destructor
+ ~TAO_LF_Event_Loop_Thread_Helper (void);
+
+ /// Calls <set_event_loop_thread> on the leader/followers object.
+ int set_event_loop_thread (ACE_Time_Value *max_wait_time);
+
+private:
+ /// Reference to leader/followers object.
+ TAO_Leader_Follower &leader_follower_;
+
+ TAO_LF_Strategy &lf_strategy_;
+
+ /// Remembers whether we have to call the reset method in the
+ /// destructor.
+ int call_reset_;
+};
+
+class TAO_Export TAO_LF_Strategy
+{
+public:
+ TAO_LF_Strategy ();
+
+ virtual ~TAO_LF_Strategy ();
+
+ virtual void set_upcall_thread (TAO_Leader_Follower &leader_follower) = 0;
+
+ virtual int set_event_loop_thread (ACE_Time_Value *max_wait_time,
+ TAO_Leader_Follower &leader_follower) = 0;
+
+ virtual void reset_event_loop_thread_and_elect_new_leader (int call_reset,
+ TAO_Leader_Follower &leader_follower) = 0;
+};
+
+class TAO_Export TAO_Complete_LF_Strategy : public TAO_LF_Strategy
+{
+public:
+ TAO_Complete_LF_Strategy ();
+
+ virtual ~TAO_Complete_LF_Strategy ();
+
+ virtual void set_upcall_thread (TAO_Leader_Follower &leader_follower);
+
+ virtual int set_event_loop_thread (ACE_Time_Value *max_wait_time,
+ TAO_Leader_Follower &leader_follower);
+
+ virtual void reset_event_loop_thread_and_elect_new_leader (int call_reset,
+ TAO_Leader_Follower &leader_follower);
+};
+
+class TAO_Export TAO_Null_LF_Strategy : public TAO_LF_Strategy
+{
+public:
+ TAO_Null_LF_Strategy ();
+
+ virtual ~TAO_Null_LF_Strategy ();
+
+ virtual void set_upcall_thread (TAO_Leader_Follower &leader_follower);
+
+ virtual int set_event_loop_thread (ACE_Time_Value *max_wait_time,
+ TAO_Leader_Follower &leader_follower);
+
+ virtual void reset_event_loop_thread_and_elect_new_leader (int call_reset,
+ TAO_Leader_Follower &leader_follower);
+};
+
#if defined (__ACE_INLINE__)
# include "tao/Leader_Follower.i"
#endif /* __ACE_INLINE__ */