00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Leader_Follower.h 00006 * 00007 * $Id: Leader_Follower.h 90990 2010-07-05 11:43:27Z johnnyw $ 00008 * 00009 * @author Carlos O'Ryan (coryan@cs.wustl.edu) 00010 */ 00011 //============================================================================= 00012 00013 00014 #ifndef TAO_LEADER_FOLLOWER_H 00015 #define TAO_LEADER_FOLLOWER_H 00016 00017 #include /**/ "ace/pre.h" 00018 #include "ace/os_include/os_errno.h" 00019 00020 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00021 # pragma once 00022 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00023 00024 #include "tao/New_Leader_Generator.h" 00025 #include "tao/LF_Follower.h" 00026 #include "ace/Reverse_Lock_T.h" 00027 #include "ace/Intrusive_List.h" 00028 #include "ace/Intrusive_List_Node.h" 00029 #include "ace/OS_NS_Thread.h" 00030 00031 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00032 class ACE_Reactor; 00033 ACE_END_VERSIONED_NAMESPACE_DECL 00034 00035 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00036 00037 class TAO_LF_Event; 00038 class TAO_Transport; 00039 class TAO_ORB_Core; 00040 class TAO_ORB_Core_TSS_Resources; 00041 00042 /** 00043 * @class TAO_Leader_Follower 00044 * 00045 * @brief TAO_Leader_Follower 00046 * 00047 * TAO_Leader_Follower 00048 */ 00049 class TAO_Export TAO_Leader_Follower 00050 { 00051 public: 00052 /// Constructor 00053 TAO_Leader_Follower (TAO_ORB_Core *orb_core, 00054 TAO_New_Leader_Generator *new_leader_generator = 0); 00055 00056 /// Destructor 00057 ~TAO_Leader_Follower (void); 00058 00059 /// The current thread has become a server thread (i.e. called 00060 /// ORB::run), update any flags and counters. 00061 int set_event_loop_thread (ACE_Time_Value *max_wait_time); 00062 00063 /// The current thread is not a server thread anymore, reset any 00064 /// flags and counters. 00065 void reset_event_loop_thread (void); 00066 00067 /// This thread is going to perform an upcall, it will no longer be 00068 /// an event loop thread. 00069 void set_upcall_thread (void); 00070 00071 /// Is there any thread running as a leader? 00072 int leader_available (void) const; 00073 00074 /// A server thread is making a request. 00075 void set_client_thread (void); 00076 00077 /// A server thread has finished is making a request. 00078 void reset_client_thread (void); 00079 00080 /// Wait on the Leader/Followers loop until one event happens. 00081 /** 00082 * @param event The event we wait for, the loop iterates until the 00083 * event is sucessful, or it fails due to timeout, and error or a 00084 * connection closed. 00085 * @param transport The transport attached to the event 00086 * @param max_wait_time Limit the time spent on the loop 00087 * @return Returns -1 on error, 0 or non-zero value 00088 * otherwise. 00089 * 00090 * @todo Document this better, split the Follower code to the 00091 * TAO_LF_Follower class, we probably don't need the transport 00092 * object. 00093 */ 00094 int wait_for_event (TAO_LF_Event *event, 00095 TAO_Transport *transport, 00096 ACE_Time_Value *max_wait_time); 00097 00098 /// The current thread has become the leader thread in the 00099 /// client side leader-follower set. 00100 void set_client_leader_thread (void) ; 00101 00102 /// The current thread is no longer the leader thread in the client 00103 /// side leader-follower set. 00104 void reset_client_leader_thread (void) ; 00105 00106 /// sets the thread ID of the leader thread in the leader-follower 00107 /// model 00108 void set_client_leader_thread (ACE_thread_t thread_ID); 00109 00110 /// checks if we are a leader thread 00111 int is_client_leader_thread (void) const; 00112 00113 /** 00114 * A leader thread is relinquishing its role, unless there are more 00115 * leader threads running pick up a follower (if there is any) to 00116 * play the leader role. 00117 */ 00118 int elect_new_leader (void); 00119 00120 /** @name Follower creation/destructions 00121 * 00122 * The Leader/Followers set acts as a factory for the Follower 00123 * objects. Followers are used to represent a thread blocked 00124 * waiting in the Follower set. 00125 * 00126 * The Leader/Followers abstraction keeps a list of the waiting 00127 * followers, so it can wake up one when the leader thread stops 00128 * handling events. 00129 * 00130 * For performance reasons the Leader/Followers set uses a pool (or 00131 * free-list) to keep Follower objects unattached to any thread. It 00132 * could be tempting to use TSS to keep such followers, after all a 00133 * thread can only need one such Follower object, however, that does 00134 * not work with multiple Leader/Followers sets, consult this bug 00135 * report for more details: 00136 * 00137 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=296 00138 * 00139 */ 00140 //@{ 00141 /// Allocate a new follower to the caller. 00142 TAO_LF_Follower *allocate_follower (void); 00143 00144 /// The caller has finished using a follower. 00145 void release_follower (TAO_LF_Follower *); 00146 //@} 00147 00148 /** @name Follower Set Operations 00149 * 00150 */ 00151 //@{ 00152 /// Add a new follower to the set 00153 void add_follower (TAO_LF_Follower *follower); 00154 00155 /// Removes a follower from the leader-follower set 00156 void remove_follower (TAO_LF_Follower *follower); 00157 00158 /// Checks if there are any followers available 00159 /** 00160 * @return 1 if there follower set is not empty 00161 */ 00162 int follower_available (void) const; 00163 00164 //@} 00165 00166 /// Get a reference to the underlying mutex 00167 TAO_SYNCH_MUTEX &lock (void); 00168 00169 /// Provide a pre-initialized reverse lock for the Leader/Followers 00170 /// set. 00171 /** 00172 * The Leader/Followers set mutex must be release during some long 00173 * running operations. This helper class simplifies the process of 00174 * releasing and reacquiring said mutex. 00175 */ 00176 ACE_Reverse_Lock<TAO_SYNCH_MUTEX> &reverse_lock (void); 00177 00178 /// Check if there are any client threads running 00179 int has_clients (void) const; 00180 00181 /// Accesor to the reactor 00182 ACE_Reactor *reactor (void); 00183 00184 /// Called when we are out of leaders. 00185 void no_leaders_available (void); 00186 00187 /// Set the new leader generator. 00188 void set_new_leader_generator(TAO_New_Leader_Generator *new_leader_generator); 00189 00190 private: 00191 /// Shortcut to obtain the TSS resources of the orb core. 00192 TAO_ORB_Core_TSS_Resources *get_tss_resources (void) const; 00193 00194 /// Wait for the client leader to complete. 00195 int wait_for_client_leader_to_complete (ACE_Time_Value *max_wait_time); 00196 00197 /** 00198 * Implement the reset_event_loop_thread() method, once the TSS 00199 * resources have been acquired. 00200 * Also used in the set_upcall_thread. 00201 */ 00202 void reset_event_loop_thread_i (TAO_ORB_Core_TSS_Resources *tss); 00203 00204 /** @name Follower Set Operations 00205 * 00206 */ 00207 //@{ 00208 /// Remote a follower from the Followers set and promote it to the 00209 /// leader role. 00210 /** 00211 * This is a helper routine for elect_new_leader(), after verifying 00212 * that all the pre-conditions are satisfied the Follower set is 00213 * changed and the promoted Follower is signaled. 00214 */ 00215 int elect_new_leader_i (void); 00216 00217 //@} 00218 00219 private: 00220 /// The orb core 00221 TAO_ORB_Core *orb_core_; 00222 00223 /// To synchronize access to the members. 00224 TAO_SYNCH_MUTEX lock_; 00225 00226 /// Do protect the access to the following three members 00227 ACE_Reverse_Lock<TAO_SYNCH_MUTEX> reverse_lock_; 00228 00229 /// Implement the Leader/Followers set using an intrusive list 00230 typedef ACE_Intrusive_List<TAO_LF_Follower> Follower_Set; 00231 Follower_Set follower_set_; 00232 00233 /// Use a free list to allocate and release Follower objects 00234 Follower_Set follower_free_list_; 00235 00236 /** 00237 * Count the number of active leaders. 00238 * There could be many leaders in the thread pool (i.e. calling 00239 * ORB::run), and the same leader could show up multiple times as it 00240 * receives nested upcalls and sends more requests. 00241 */ 00242 int leaders_; 00243 00244 /// Count the number of active clients, this is useful to know when 00245 /// to deactivate the reactor 00246 int clients_; 00247 00248 /// The reactor 00249 ACE_Reactor *reactor_; 00250 00251 /// Is a client thread the current leader? 00252 int client_thread_is_leader_; 00253 00254 /// Are server threads waiting for the client leader to complete? 00255 int event_loop_threads_waiting_; 00256 00257 /// Condition variable for server threads waiting for the client 00258 /// leader to complete. 00259 TAO_SYNCH_CONDITION event_loop_threads_condition_; 00260 00261 /// Leader/Follower class uses this method to notify the system that 00262 /// we are out of leaders. 00263 TAO_New_Leader_Generator *new_leader_generator_; 00264 }; 00265 00266 class TAO_Export TAO_LF_Client_Thread_Helper 00267 { 00268 public: 00269 /// Constructor 00270 TAO_LF_Client_Thread_Helper (TAO_Leader_Follower &leader_follower); 00271 00272 /// Destructor 00273 ~TAO_LF_Client_Thread_Helper (void); 00274 00275 private: 00276 /// Reference to leader/followers object. 00277 TAO_Leader_Follower &leader_follower_; 00278 }; 00279 00280 class TAO_Export TAO_LF_Client_Leader_Thread_Helper 00281 { 00282 public: 00283 /// Constructor 00284 TAO_LF_Client_Leader_Thread_Helper (TAO_Leader_Follower &leader_follower); 00285 00286 /// Destructor 00287 ~TAO_LF_Client_Leader_Thread_Helper (void); 00288 00289 private: 00290 /// Reference to leader/followers object. 00291 TAO_Leader_Follower &leader_follower_; 00292 }; 00293 00294 TAO_END_VERSIONED_NAMESPACE_DECL 00295 00296 #if defined (__ACE_INLINE__) 00297 # include "tao/Leader_Follower.inl" 00298 #endif /* __ACE_INLINE__ */ 00299 00300 #include /**/ "ace/post.h" 00301 00302 #endif /* TAO_LEADER_FOLLOWER_H */