2 // ****************************************************************
4 #include "tao/ORB_Core_TSS_Resources.h"
5 #include "tao/ORB_Core.h"
7 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
10 TAO_Leader_Follower::TAO_Leader_Follower (TAO_ORB_Core* orb_core,
11 TAO_New_Leader_Generator *new_leader_generator)
12 : orb_core_ (orb_core),
13 reverse_lock_ (lock_),
17 avoid_client_leader_ (false),
18 client_thread_is_leader_ (0),
19 event_loop_threads_waiting_ (0),
20 event_loop_threads_condition_ (lock_),
21 new_leader_generator_ (new_leader_generator)
25 ACE_INLINE TAO_ORB_Core_TSS_Resources *
26 TAO_Leader_Follower::get_tss_resources () const
28 return this->orb_core_->get_tss_resources ();
32 TAO_Leader_Follower::set_avoid_client_leader ()
34 this->avoid_client_leader_ = true;
38 TAO_Leader_Follower::follower_available () const
40 return !this->follower_set_.is_empty ();
44 TAO_Leader_Follower::no_leaders_available ()
46 if (this->new_leader_generator_)
47 return this->new_leader_generator_->no_leaders_available ();
52 TAO_Leader_Follower::elect_new_leader ()
54 if (this->leaders_ == 0)
56 if (this->event_loop_threads_waiting_)
58 return this->event_loop_threads_condition_.broadcast ();
60 else if (this->follower_available ())
62 return this->elect_new_leader_i ();
66 this->no_leaders_available ();
73 TAO_Leader_Follower::set_event_loop_thread (ACE_Time_Value *max_wait_time)
75 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
77 // Make sure that there is no other client thread run the show. If
78 // we are the client thread running the show, then it is ok.
79 if (this->client_thread_is_leader_ &&
80 tss->client_leader_thread_ == 0)
83 this->wait_for_client_leader_to_complete (max_wait_time);
89 // If <event_loop_thread_> == 0 and <client_leader_thread_> == 0, we
90 // are running the event loop for the first time. Therefore,
91 // increment the leaders. Otherwise, simply increment
92 // <event_loop_thread_> since either (a) if <event_loop_thread_> !=
93 // 0 this is a nested call to the event loop, or (b)
94 // <client_leader_thread_> != 0 this is a call to the event loop
95 // while we are a client leader.
96 if (tss->event_loop_thread_ == 0 &&
97 tss->client_leader_thread_ == 0)
100 ++tss->event_loop_thread_;
106 TAO_Leader_Follower::reset_event_loop_thread_i (TAO_ORB_Core_TSS_Resources *tss)
108 // Always decrement <event_loop_thread_>. If <event_loop_thread_>
109 // reaches 0 and we are not a client leader, we are done with our
110 // duties of running the event loop. Therefore, decrement the
111 // leaders. Otherwise, we just got done with a nested call to the
112 // event loop or a call to the event loop when we were the client
114 --tss->event_loop_thread_;
116 if (tss->event_loop_thread_ == 0 &&
117 tss->client_leader_thread_ == 0)
122 TAO_Leader_Follower::reset_event_loop_thread ()
124 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
125 if (tss->event_loop_thread_ > 0)
126 this->reset_event_loop_thread_i (tss);
129 ACE_INLINE TAO_SYNCH_MUTEX &
130 TAO_Leader_Follower::lock ()
136 TAO_Leader_Follower::set_upcall_thread ()
138 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
140 if (tss->event_loop_thread_ > 0)
142 ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock ());
143 this->reset_event_loop_thread_i (tss);
145 this->elect_new_leader ();
147 else if (tss->client_leader_thread_ == 1)
148 { // We are client leader thread going to handle upcall.
149 // When we're only leading one level (which should
150 // now always be the case since we implement leadership
151 // abdication here) we can now give up leadership to allow a
152 // waiting event thread to take over leaderpship
153 ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock ());
154 this->reset_client_leader_thread ();
156 this->elect_new_leader ();
161 TAO_Leader_Follower::leader_available () const
163 return this->leaders_ != 0;
167 TAO_Leader_Follower::set_client_leader_thread ()
169 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
171 ++this->client_thread_is_leader_;
172 ++tss->client_leader_thread_;
176 TAO_Leader_Follower::reset_client_leader_thread ()
178 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
179 // We may be called twice when we gave up leadership from
180 // set_upcall_thread () if so tss->client_leader_thread_ may
181 // already have been decremented to 0
182 if (tss->client_leader_thread_ > 0)
184 --tss->client_leader_thread_;
186 --this->client_thread_is_leader_;
191 TAO_Leader_Follower::is_client_leader_thread () const
193 TAO_ORB_Core_TSS_Resources *tss = this->get_tss_resources ();
194 return tss->client_leader_thread_ != 0;
198 TAO_Leader_Follower::add_follower (TAO_LF_Follower *follower)
200 this->follower_set_.push_back (follower);
204 TAO_Leader_Follower::remove_follower (TAO_LF_Follower *follower)
206 this->follower_set_.remove (follower);
209 ACE_INLINE ACE_Reverse_Lock<TAO_SYNCH_MUTEX> &
210 TAO_Leader_Follower::reverse_lock ()
212 return this->reverse_lock_;
216 TAO_Leader_Follower::has_clients () const
218 return this->clients_;
222 TAO_Leader_Follower::set_new_leader_generator(TAO_New_Leader_Generator *new_leader_generator)
224 this->new_leader_generator_ = new_leader_generator;
227 // ****************************************************************
230 TAO_LF_Client_Thread_Helper::TAO_LF_Client_Thread_Helper (TAO_Leader_Follower &leader_follower)
231 : leader_follower_ (leader_follower)
233 this->leader_follower_.set_client_thread ();
237 TAO_LF_Client_Thread_Helper::~TAO_LF_Client_Thread_Helper ()
239 this->leader_follower_.reset_client_thread ();
243 TAO_LF_Client_Leader_Thread_Helper::TAO_LF_Client_Leader_Thread_Helper (TAO_Leader_Follower &leader_follower)
244 : leader_follower_ (leader_follower)
246 this->leader_follower_.set_client_leader_thread ();
250 TAO_LF_Client_Leader_Thread_Helper::~TAO_LF_Client_Leader_Thread_Helper ()
252 this->leader_follower_.reset_client_leader_thread ();
255 TAO_END_VERSIONED_NAMESPACE_DECL