gnuace: use list of generated files from GENERATED_DIRTY for ADDITIONAL_IDL_TARGETS
[ACE_TAO.git] / ACE / ace / Thread_Manager.cpp
blob172e4a43af843a2dd00822c735be105d9e70b966
1 #include "ace/TSS_T.h"
2 #include "ace/Thread_Manager.h"
3 #include "ace/Dynamic.h"
4 #include "ace/Object_Manager.h"
5 #include "ace/Singleton.h"
6 #include "ace/Auto_Ptr.h"
7 #include "ace/Guard_T.h"
8 #include "ace/Time_Value.h"
9 #include "ace/OS_NS_sys_time.h"
10 #include "ace/Truncate.h"
12 #if !defined (__ACE_INLINE__)
13 #include "ace/Thread_Manager.inl"
14 #endif /* __ACE_INLINE__ */
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_At_Thread_Exit::~ACE_At_Thread_Exit (void)
20 this->do_apply ();
23 ACE_At_Thread_Exit_Func::~ACE_At_Thread_Exit_Func (void)
25 this->do_apply ();
28 ACE_ALLOC_HOOK_DEFINE(ACE_At_Thread_Exit_Func)
30 void
31 ACE_At_Thread_Exit_Func::apply (void)
33 this->func_ (this->object_, this->param_);
36 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Control)
37 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Manager)
39 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
40 // Process-wide Thread Manager.
41 ACE_Thread_Manager *ACE_Thread_Manager::thr_mgr_ = 0;
43 // Controls whether the Thread_Manager is deleted when we shut down
44 // (we can only delete it safely if we created it!)
45 bool ACE_Thread_Manager::delete_thr_mgr_ = false;
46 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
48 ACE_TSS_TYPE (ACE_Thread_Exit) *ACE_Thread_Manager::thr_exit_ = 0;
50 int
51 ACE_Thread_Manager::set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr)
53 if (ACE_Thread_Manager::thr_exit_ == 0)
54 ACE_Thread_Manager::thr_exit_ = ptr;
55 else
56 return -1;
57 return 0;
60 void
61 ACE_Thread_Manager::dump (void)
63 #if defined (ACE_HAS_DUMP)
64 ACE_TRACE ("ACE_Thread_Manager::dump");
65 // Cast away const-ness of this in order to use its non-const lock_.
66 ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon,
67 ((ACE_Thread_Manager *) this)->lock_));
69 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
71 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
72 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncurrent_count_ = %d"), this->thr_list_.size ()));
74 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
75 !iter.done ();
76 iter.advance ())
78 iter.next ()->dump ();
81 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
82 #endif /* ACE_HAS_DUMP */
85 ACE_Thread_Descriptor::~ACE_Thread_Descriptor (void)
87 delete this->sync_;
90 void
91 ACE_Thread_Descriptor::at_pop (int apply)
93 ACE_TRACE ("ACE_Thread_Descriptor::at_pop");
94 // Get first at from at_exit_list
95 ACE_At_Thread_Exit* at = this->at_exit_list_;
96 // Remove at from at_exit list
97 this->at_exit_list_ = at->next_;
98 // Apply if required
99 if (apply)
101 at->apply ();
102 // Do the apply method
103 at->was_applied (true);
104 // Mark at has been applied to avoid double apply from
105 // at destructor
107 // If at is not owner delete at.
108 if (!at->is_owner ())
109 delete at;
112 void
113 ACE_Thread_Descriptor::at_push (ACE_At_Thread_Exit* cleanup, bool is_owner)
115 ACE_TRACE ("ACE_Thread_Descriptor::at_push");
116 cleanup->is_owner (is_owner);
117 cleanup->td_ = this;
118 cleanup->next_ = at_exit_list_;
119 at_exit_list_ = cleanup;
123 ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit& cleanup)
125 ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
126 at_push (&cleanup, 1);
127 return 0;
131 ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit* cleanup)
133 ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
134 if (cleanup==0)
135 return -1;
136 else
138 this->at_push (cleanup);
139 return 0;
143 void
144 ACE_Thread_Descriptor::do_at_exit ()
146 ACE_TRACE ("ACE_Thread_Descriptor::do_at_exit");
147 while (at_exit_list_!=0)
148 this->at_pop ();
151 void
152 ACE_Thread_Descriptor::terminate ()
154 ACE_TRACE ("ACE_Thread_Descriptor::terminate");
156 if (!terminated_)
158 ACE_Log_Msg* log_msg = this->log_msg_;
159 terminated_ = true;
160 // Run at_exit hooks
161 this->do_at_exit ();
162 // We must remove Thread_Descriptor from Thread_Manager list
163 if (this->tm_ != 0)
165 int close_handle = 0;
167 #if !defined (ACE_HAS_VXTHREADS)
168 // Threads created with THR_DAEMON shouldn't exist here, but
169 // just to be safe, let's put it here.
171 if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_JOINING))
173 if (ACE_BIT_DISABLED (this->flags_, THR_DETACHED | THR_DAEMON)
174 || ACE_BIT_ENABLED (this->flags_, THR_JOINABLE))
176 // Mark thread as terminated.
177 ACE_SET_BITS (this->thr_state_, ACE_Thread_Manager::ACE_THR_TERMINATED);
178 tm_->register_as_terminated (this);
179 // Must copy the information here because td will be
180 // "freed" below.
182 #if defined (ACE_WIN32)
183 else
185 close_handle = 1;
187 #endif /* ACE_WIN32 */
189 #endif /* !ACE_HAS_VXTHREADS */
191 // Remove thread descriptor from the table. 'this' is invalid
192 // upon return.
193 if (this->tm_ != 0)
195 // remove_thr makes use of 'this' invalid on return.
196 // Code below will free log_msg, so clear our pointer
197 // now - it's already been saved in log_msg.
198 this->log_msg_ = 0;
199 tm_->remove_thr (this, close_handle);
203 // Check if we need delete ACE_Log_Msg instance
204 // If ACE_TSS_cleanup was not executed first log_msg == 0
205 if (log_msg == 0)
207 // Only inform to ACE_TSS_cleanup that it must delete the log instance
208 // setting ACE_LOG_MSG thr_desc to 0.
209 ACE_LOG_MSG->thr_desc (0);
211 else
213 delete log_msg;
219 ACE_Thread_Descriptor::at_exit (void *object,
220 ACE_CLEANUP_FUNC cleanup_hook,
221 void *param)
223 ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
224 // To keep compatibility, when cleanup_hook is null really is a at_pop
225 // without apply.
226 if (cleanup_hook == 0)
228 if (this->at_exit_list_!= 0)
229 this->at_pop(0);
231 else
233 ACE_At_Thread_Exit* cleanup = 0;
234 ACE_NEW_RETURN (cleanup,
235 ACE_At_Thread_Exit_Func (object,
236 cleanup_hook,
237 param),
238 -1);
239 this->at_push (cleanup);
241 return 0;
244 void
245 ACE_Thread_Descriptor::dump (void) const
247 #if defined (ACE_HAS_DUMP)
248 ACE_TRACE ("ACE_Thread_Descriptor::dump");
249 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
251 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_id_ = %d"), this->thr_id_));
252 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_handle_ = %d"), this->thr_handle_));
253 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_));
254 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_state_ = %d"), this->thr_state_));
255 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %x\n"), this->flags_));
257 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
258 #endif /* ACE_HAS_DUMP */
261 ACE_Thread_Descriptor::ACE_Thread_Descriptor (void)
262 : log_msg_ (0),
263 at_exit_list_ (0),
264 tm_ (0),
265 terminated_ (false)
267 ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor");
268 ACE_NEW (this->sync_,
269 ACE_DEFAULT_THREAD_MANAGER_LOCK);
272 void
273 ACE_Thread_Descriptor::acquire_release (void)
275 // Just try to acquire the lock then release it.
276 #if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
277 if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
278 #endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
280 this->sync_->acquire ();
281 // Acquire the lock before removing <td> from the thread table. If
282 // this thread is in the table already, it should simply acquire the
283 // lock easily.
285 // Once we get the lock, we must have registered.
286 ACE_ASSERT (ACE_BIT_ENABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED));
288 this->sync_->release ();
289 // Release the lock before putting it back to freelist.
293 void
294 ACE_Thread_Descriptor::acquire (void)
296 // Just try to acquire the lock then release it.
297 #if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
298 if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
299 #endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
301 this->sync_->acquire ();
305 void
306 ACE_Thread_Descriptor::release (void)
308 // Just try to acquire the lock then release it.
309 #if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN)
310 if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED))
311 #endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */
313 this->sync_->release ();
314 // Release the lock before putting it back to freelist.
318 // The following macro simplifies subsequence code.
319 #define ACE_FIND(OP,INDEX) \
320 ACE_Thread_Descriptor *INDEX = OP; \
322 ACE_Thread_Descriptor *
323 ACE_Thread_Manager::thread_descriptor (ACE_thread_t thr_id)
325 ACE_TRACE ("ACE_Thread_Manager::thread_descriptor");
326 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
328 ACE_FIND (this->find_thread (thr_id), ptr);
329 return ptr;
332 ACE_Thread_Descriptor *
333 ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle)
335 ACE_TRACE ("ACE_Thread_Manager::hthread_descriptor");
336 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
338 ACE_FIND (this->find_hthread (thr_handle), ptr);
339 return ptr;
342 // Return the thread descriptor (indexed by ACE_hthread_t).
345 ACE_Thread_Manager::thr_self (ACE_hthread_t &self)
347 ACE_TRACE ("ACE_Thread_Manager::thr_self");
349 ACE_Thread_Descriptor *desc =
350 this->thread_desc_self ();
352 if (desc == 0)
353 return -1;
354 else
355 desc->self (self);
357 return 0;
360 // Initialize the synchronization variables.
362 ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc,
363 size_t lwm,
364 size_t inc,
365 size_t hwm)
366 : grp_id_ (1),
367 automatic_wait_ (1)
368 #if defined (ACE_HAS_THREADS)
369 , zero_cond_ (lock_)
370 #endif /* ACE_HAS_THREADS */
371 , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL,
372 prealloc, lwm, hwm, inc)
373 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
374 , join_cond_ (this->lock_)
375 #endif
377 ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
380 ACE_Thread_Manager::ACE_Thread_Manager (const ACE_Condition_Attributes &attributes,
381 size_t prealloc,
382 size_t lwm,
383 size_t inc,
384 size_t hwm)
385 : grp_id_ (1),
386 automatic_wait_ (1)
387 #if defined (ACE_HAS_THREADS)
388 , zero_cond_ (lock_, attributes)
389 #endif /* ACE_HAS_THREADS */
390 , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL,
391 prealloc, lwm, hwm, inc)
392 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
393 , join_cond_ (this->lock_)
394 #endif
396 #if !defined (ACE_HAS_THREADS)
397 ACE_UNUSED_ARG (attributes);
398 #endif /* ACE_HAS_THREADS */
399 ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
402 #if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
403 ACE_Thread_Manager *
404 ACE_Thread_Manager::instance (void)
406 ACE_TRACE ("ACE_Thread_Manager::instance");
408 if (ACE_Thread_Manager::thr_mgr_ == 0)
410 // Perform Double-Checked Locking Optimization.
411 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
412 *ACE_Static_Object_Lock::instance (), 0));
414 if (ACE_Thread_Manager::thr_mgr_ == 0)
416 ACE_NEW_RETURN (ACE_Thread_Manager::thr_mgr_,
417 ACE_Thread_Manager,
419 ACE_Thread_Manager::delete_thr_mgr_ = true;
423 return ACE_Thread_Manager::thr_mgr_;
426 ACE_Thread_Manager *
427 ACE_Thread_Manager::instance (ACE_Thread_Manager *tm)
429 ACE_TRACE ("ACE_Thread_Manager::instance");
430 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
431 *ACE_Static_Object_Lock::instance (), 0));
433 ACE_Thread_Manager *t = ACE_Thread_Manager::thr_mgr_;
434 // We can't safely delete it since we don't know who created it!
435 ACE_Thread_Manager::delete_thr_mgr_ = false;
437 ACE_Thread_Manager::thr_mgr_ = tm;
438 return t;
441 void
442 ACE_Thread_Manager::close_singleton (void)
444 ACE_TRACE ("ACE_Thread_Manager::close_singleton");
446 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
447 *ACE_Static_Object_Lock::instance ()));
449 if (ACE_Thread_Manager::delete_thr_mgr_)
451 // First, we clean up the thread descriptor list.
452 ACE_Thread_Manager::thr_mgr_->close ();
453 delete ACE_Thread_Manager::thr_mgr_;
454 ACE_Thread_Manager::thr_mgr_ = 0;
455 ACE_Thread_Manager::delete_thr_mgr_ = false;
458 ACE_Thread_Exit::cleanup (ACE_Thread_Manager::thr_exit_);
460 #endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
462 // Close up and release all resources.
465 ACE_Thread_Manager::close ()
467 ACE_TRACE ("ACE_Thread_Manager::close");
469 // Clean up the thread descriptor list.
470 if (this->automatic_wait_)
471 this->wait (0, 1);
472 else
474 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
476 this->remove_thr_all ();
479 return 0;
482 ACE_Thread_Manager::~ACE_Thread_Manager (void)
484 ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager");
485 this->close ();
489 // Run the entry point for thread spawned under the control of the
490 // <ACE_Thread_Manager>. This must be an extern "C" to make certain
491 // compilers happy...
493 // The interaction with <ACE_Thread_Exit> and
494 // <ace_thread_manager_adapter> works like this, with
495 // ACE_HAS_THREAD_SPECIFIC_STORAGE or ACE_HAS_TSS_EMULATION:
497 // o Every thread in the <ACE_Thread_Manager> is run with
498 // <ace_thread_manager_adapter>.
500 // o <ace_thread_manager_adapter> retrieves the singleton
501 // <ACE_Thread_Exit> instance from <ACE_Thread_Exit::instance>.
502 // The singleton gets created in thread-specific storage
503 // in the first call to that function. The key point is that the
504 // instance is in thread-specific storage.
506 // o A thread can exit by various means, such as <ACE_Thread::exit>, C++
507 // or Win32 exception, "falling off the end" of the thread entry
508 // point function, etc.
510 // o If you follow this so far, now it gets really fun . . .
511 // When the thread-specific storage (for the thread that
512 // is being destroyed) is cleaned up, the OS threads package (or
513 // the ACE emulation of thread-specific storage) will destroy any
514 // objects that are in thread-specific storage. It has a list of
515 // them, and just walks down the list and destroys each one.
517 // o That's where the ACE_Thread_Exit destructor gets called.
519 #if defined(ACE_USE_THREAD_MANAGER_ADAPTER)
520 extern "C" void *
521 ace_thread_manager_adapter (void *args)
523 #if defined (ACE_HAS_TSS_EMULATION)
524 // As early as we can in the execution of the new thread, allocate
525 // its local TS storage. Allocate it on the stack, to save dynamic
526 // allocation/dealloction.
527 void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
528 ACE_TSS_Emulation::tss_open (ts_storage);
529 #endif /* ACE_HAS_TSS_EMULATION */
531 ACE_Thread_Adapter *thread_args = reinterpret_cast<ACE_Thread_Adapter *> (args);
533 // NOTE: this preprocessor directive should match the one in above
534 // ACE_Thread_Exit::instance (). With the Xavier Pthreads package,
535 // the exit_hook in TSS causes a seg fault. So, this works around
536 // that by creating exit_hook on the stack.
537 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)
538 // Obtain our thread-specific exit hook and make sure that it knows
539 // how to clean us up! Note that we never use this pointer directly
540 // (it's stored in thread-specific storage), so it's ok to
541 // dereference it here and only store it as a reference.
542 ACE_Thread_Exit &exit_hook = *ACE_Thread_Exit::instance ();
543 #else
544 // Without TSS, create an <ACE_Thread_Exit> instance. When this
545 // function returns, its destructor will be called because the
546 // object goes out of scope. The drawback with this appraoch is
547 // that the destructor _won't_ get called if <thr_exit> is called.
548 // So, threads shouldn't exit that way. Instead, they should return
549 // from <svc>.
550 ACE_Thread_Exit exit_hook;
551 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
553 // Keep track of the <Thread_Manager> that's associated with this
554 // <exit_hook>.
555 exit_hook.thr_mgr (thread_args->thr_mgr ());
557 // Invoke the user-supplied function with the args.
558 ACE_THR_FUNC_RETURN status = thread_args->invoke ();
560 delete static_cast<ACE_Base_Thread_Adapter *> (thread_args);
562 return reinterpret_cast<void *> (status);
564 #endif
566 // Call the appropriate OS routine to spawn a thread. Should *not* be
567 // called with the lock_ held...
570 ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func,
571 void *args,
572 long flags,
573 ACE_thread_t *t_id,
574 ACE_hthread_t *t_handle,
575 long priority,
576 int grp_id,
577 void *stack,
578 size_t stack_size,
579 ACE_Task_Base *task,
580 const char** thr_name)
582 // First, threads created by Thread Manager should not be daemon threads.
583 // Using assertion is probably a bit too strong. However, it helps
584 // finding this kind of error as early as possible. Perhaps we can replace
585 // assertion by returning error.
586 ACE_ASSERT (ACE_BIT_DISABLED (flags, THR_DAEMON));
588 // Create a new thread running <func>. *Must* be called with the
589 // <lock_> held...
590 // Get a "new" Thread Descriptor from the freelist.
591 #if defined (ACE_HAS_CPP11)
592 std::unique_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ());
593 #else
594 auto_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ());
595 #endif /* ACE_HAS_CPP11 */
597 // Reset thread descriptor status
598 new_thr_desc->reset (this);
600 ACE_Thread_Adapter *thread_args = 0;
601 # if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
602 ACE_NEW_RETURN (thread_args,
603 ACE_Thread_Adapter (func,
604 args,
605 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
606 this,
607 new_thr_desc.get (),
608 ACE_OS_Object_Manager::seh_except_selector(),
609 ACE_OS_Object_Manager::seh_except_handler(),
610 flags),
611 -1);
612 # else
613 ACE_NEW_RETURN (thread_args,
614 ACE_Thread_Adapter (func,
615 args,
616 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
617 this,
618 new_thr_desc.get (),
619 flags),
620 -1);
621 # endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
622 #if defined ACE_HAS_CPP11
623 std::unique_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args));
624 #else
625 auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args));
626 #endif
628 ACE_TRACE ("ACE_Thread_Manager::spawn_i");
629 ACE_hthread_t thr_handle;
631 ACE_thread_t thr_id;
632 if (t_id == 0)
633 t_id = &thr_id;
635 // Acquire the <sync_> lock to block the spawned thread from
636 // removing this Thread Descriptor before it gets put into our
637 // thread table.
638 new_thr_desc->sync_->acquire ();
640 int const result = ACE_Thread::spawn (func,
641 args,
642 flags,
643 t_id,
644 &thr_handle,
645 priority,
646 stack,
647 stack_size,
648 thread_args,
649 thr_name);
651 if (result != 0)
653 // _Don't_ clobber errno here! result is either 0 or -1, and
654 // ACE_OS::thr_create () already set errno! D. Levine 28 Mar 1997
655 // errno = result;
656 ACE_Errno_Guard guard (errno); // Lock release may smash errno
657 new_thr_desc->sync_->release ();
658 return -1;
660 auto_thread_args.release ();
662 #if defined (ACE_HAS_WTHREADS)
663 // Have to duplicate handle if client asks for it.
664 // @@ How are thread handles implemented on AIX? Do they
665 // also need to be duplicated?
666 if (t_handle != 0)
667 # if defined (ACE_LACKS_DUPLICATEHANDLE)
668 *t_handle = thr_handle;
669 # else /* ! ACE_LACKS_DUP */
670 (void) ::DuplicateHandle (::GetCurrentProcess (),
671 thr_handle,
672 ::GetCurrentProcess (),
673 t_handle,
675 TRUE,
676 DUPLICATE_SAME_ACCESS);
677 # endif /* ! ACE_LACKS_DUP */
678 #else /* ! ACE_HAS_WTHREADS */
679 if (t_handle != 0)
680 *t_handle = thr_handle;
681 #endif /* ! ACE_HAS_WTHREADS */
683 // append_thr also put the <new_thr_desc> into Thread_Manager's
684 // double-linked list. Only after this point, can we manipulate
685 // double-linked list from a spawned thread's context.
686 return this->append_thr (*t_id,
687 thr_handle,
688 ACE_THR_SPAWNED,
689 grp_id,
690 task,
691 flags,
692 new_thr_desc.release ());
696 ACE_Thread_Manager::spawn (ACE_THR_FUNC func,
697 void *args,
698 long flags,
699 ACE_thread_t *t_id,
700 ACE_hthread_t *t_handle,
701 long priority,
702 int grp_id,
703 void *stack,
704 size_t stack_size,
705 const char** thr_name)
707 ACE_TRACE ("ACE_Thread_Manager::spawn");
709 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
711 if (grp_id == -1)
712 grp_id = this->grp_id_++; // Increment the group id.
714 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
715 ACE_CLR_BITS (flags, THR_INHERIT_SCHED);
717 if (this->spawn_i (func,
718 args,
719 flags,
720 t_id,
721 t_handle,
722 priority,
723 grp_id,
724 stack,
725 stack_size,
727 thr_name) == -1)
728 return -1;
730 return grp_id;
733 // Create N new threads running FUNC.
736 ACE_Thread_Manager::spawn_n (size_t n,
737 ACE_THR_FUNC func,
738 void *args,
739 long flags,
740 long priority,
741 int grp_id,
742 ACE_Task_Base *task,
743 ACE_hthread_t thread_handles[],
744 void *stack[],
745 size_t stack_size[],
746 const char* thr_name[])
748 ACE_TRACE ("ACE_Thread_Manager::spawn_n");
749 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
751 if (grp_id == -1)
752 grp_id = this->grp_id_++; // Increment the group id.
754 for (size_t i = 0; i < n; i++)
756 // @@ What should happen if this fails?! e.g., should we try to
757 // cancel the other threads that we've already spawned or what?
758 if (this->spawn_i (func,
759 args,
760 flags,
762 thread_handles == 0 ? 0 : &thread_handles[i],
763 priority,
764 grp_id,
765 stack == 0 ? 0 : stack[i],
766 stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
767 task,
768 thr_name == 0 ? 0 : &thr_name [i]) == -1)
769 return -1;
772 return grp_id;
775 // Create N new threads running FUNC.
778 ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
779 size_t n,
780 ACE_THR_FUNC func,
781 void *args,
782 long flags,
783 long priority,
784 int grp_id,
785 void *stack[],
786 size_t stack_size[],
787 ACE_hthread_t thread_handles[],
788 ACE_Task_Base *task,
789 const char* thr_name[])
791 ACE_TRACE ("ACE_Thread_Manager::spawn_n");
792 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
794 if (grp_id == -1)
795 grp_id = this->grp_id_++; // Increment the group id.
797 for (size_t i = 0; i < n; i++)
799 // @@ What should happen if this fails?! e.g., should we try to
800 // cancel the other threads that we've already spawned or what?
801 if (this->spawn_i (func,
802 args,
803 flags,
804 thread_ids == 0 ? 0 : &thread_ids[i],
805 thread_handles == 0 ? 0 : &thread_handles[i],
806 priority,
807 grp_id,
808 stack == 0 ? 0 : stack[i],
809 stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
810 task,
811 thr_name == 0 ? 0 : &thr_name [i]) == -1)
812 return -1;
815 return grp_id;
818 // Append a thread into the pool (does not check for duplicates).
819 // Must be called with locks held.
822 ACE_Thread_Manager::append_thr (ACE_thread_t t_id,
823 ACE_hthread_t t_handle,
824 ACE_UINT32 thr_state,
825 int grp_id,
826 ACE_Task_Base *task,
827 long flags,
828 ACE_Thread_Descriptor *td)
830 ACE_TRACE ("ACE_Thread_Manager::append_thr");
831 ACE_Thread_Descriptor *thr_desc = 0;
833 if (td == 0)
835 ACE_NEW_RETURN (thr_desc,
836 ACE_Thread_Descriptor,
837 -1);
838 thr_desc->tm_ = this;
839 // Setup the Thread_Manager.
841 else
842 thr_desc = td;
844 thr_desc->thr_id_ = t_id;
845 thr_desc->thr_handle_ = t_handle;
846 thr_desc->grp_id_ = grp_id;
847 thr_desc->task_ = task;
848 thr_desc->flags_ = flags;
850 this->thr_list_.insert_head (thr_desc);
851 ACE_SET_BITS (thr_desc->thr_state_, thr_state);
852 thr_desc->sync_->release ();
854 return 0;
857 // Return the thread descriptor (indexed by ACE_hthread_t).
859 ACE_Thread_Descriptor *
860 ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id)
862 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
863 !iter.done ();
864 iter.advance ())
866 if (ACE_OS::thr_cmp (iter.next ()->thr_handle_, h_id))
868 return iter.next ();
872 return 0;
875 // Locate the index in the table associated with <t_id>. Must be
876 // called with the lock held.
878 ACE_Thread_Descriptor *
879 ACE_Thread_Manager::find_thread (ACE_thread_t t_id)
881 ACE_TRACE ("ACE_Thread_Manager::find_thread");
883 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
884 !iter.done ();
885 iter.advance ())
887 if (ACE_OS::thr_equal (iter.next ()->thr_id_, t_id))
889 return iter.next ();
892 return 0;
895 // Insert a thread into the pool (checks for duplicates and doesn't
896 // allow them to be inserted twice).
899 ACE_Thread_Manager::insert_thr (ACE_thread_t t_id,
900 ACE_hthread_t t_handle,
901 int grp_id,
902 long flags)
904 ACE_TRACE ("ACE_Thread_Manager::insert_thr");
905 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
907 // Check for duplicates and bail out if we're already registered...
908 if (this->find_thread (t_id) != 0 )
909 return -1;
911 if (grp_id == -1)
912 grp_id = this->grp_id_++;
914 if (this->append_thr (t_id,
915 t_handle,
916 ACE_THR_SPAWNED,
917 grp_id,
919 flags) == -1)
920 return -1;
922 return grp_id;
925 // Run the registered hooks when the thread exits.
927 void
928 ACE_Thread_Manager::run_thread_exit_hooks (int i)
930 #if 0 // currently unused!
931 ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks");
933 // @@ Currently, we have just one hook. This should clearly be
934 // generalized to support an arbitrary number of hooks.
936 ACE_Thread_Descriptor *td = this->thread_desc_self ();
937 for (ACE_Cleanup_Info_Node *iter = td->cleanup_info_->pop_front ();
938 iter != 0;
939 iter = cleanup_info_->pop_front ())
941 if (iter->cleanup_hook () != 0)
943 (*iter->cleanup_hook ()) (iter->object (), iter->param ());
945 delete iter;
948 ACE_UNUSED_ARG (i);
949 #else
950 ACE_UNUSED_ARG (i);
951 #endif /* 0 */
954 // Remove a thread from the pool. Must be called with locks held.
956 void
957 ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor *td,
958 int close_handler)
960 ACE_TRACE ("ACE_Thread_Manager::remove_thr");
962 td->tm_ = 0;
963 this->thr_list_.remove (td);
965 #if defined (ACE_WIN32)
966 if (close_handler != 0)
967 ::CloseHandle (td->thr_handle_);
968 #else
969 ACE_UNUSED_ARG (close_handler);
970 #endif /* ACE_WIN32 */
972 this->thread_desc_freelist_.add (td);
974 #if defined (ACE_HAS_THREADS)
975 // Tell all waiters when there are no more threads left in the pool.
976 if (this->thr_list_.size () == 0)
977 this->zero_cond_.broadcast ();
978 #endif /* ACE_HAS_THREADS */
981 // Repeatedly call remove_thr on all table entries until there
982 // is no thread left. Must be called with lock held.
983 void
984 ACE_Thread_Manager::remove_thr_all (void)
986 ACE_Thread_Descriptor *td = 0;
988 while ((td = this->thr_list_.delete_head ()) != 0)
990 this->remove_thr (td, 1);
994 // ------------------------------------------------------------------
995 // Factor out some common behavior to simplify the following methods.
996 #define ACE_THR_OP(OP,STATE) \
997 int result = OP (td->thr_handle_); \
998 if (result == -1) { \
999 if (errno != ENOTSUP) \
1000 this->thr_to_be_removed_.enqueue_tail (td); \
1001 return -1; \
1003 else { \
1004 ACE_SET_BITS (td->thr_state_, STATE); \
1005 return 0; \
1009 ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor *td, int)
1011 ACE_TRACE ("ACE_Thread_Manager::join_thr");
1013 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1014 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1016 if (ACE_BIT_DISABLED (td->flags_, THR_DETACHED | THR_DAEMON)
1017 || ACE_BIT_ENABLED (td->flags_, THR_JOINABLE))
1019 if (td->terminated_)
1020 return 0;
1021 ACE_SET_BITS (td->thr_state_, ACE_THR_JOINING);
1023 else
1025 errno = EINVAL;
1026 return -1;
1029 const ACE_thread_t waiting_id = td->thr_id_;
1031 while (true)
1033 if (this->join_cond_.wait () == -1)
1034 return -1;
1036 bool found = false;
1037 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1038 !iter.done () && !found; iter.advance ())
1039 if (ACE_OS::thr_equal (iter.next ()->thr_id_, waiting_id))
1040 found = true;
1041 if (!found)
1042 break;
1045 #else
1046 int const result = ACE_Thread::join (td->thr_handle_);
1047 if (result != 0)
1049 // Since the thread are being joined, we should
1050 // let it remove itself from the list.
1052 // this->remove_thr (td);
1053 errno = result;
1054 return -1;
1056 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1058 return 0;
1062 ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor *td, int)
1064 ACE_TRACE ("ACE_Thread_Manager::suspend_thr");
1066 int const result = ACE_Thread::suspend (td->thr_handle_);
1067 if (result == -1) {
1068 if (errno != ENOTSUP)
1069 this->thr_to_be_removed_.enqueue_tail (td);
1070 return -1;
1072 else {
1073 ACE_SET_BITS (td->thr_state_, ACE_THR_SUSPENDED);
1074 return 0;
1079 ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor *td, int)
1081 ACE_TRACE ("ACE_Thread_Manager::resume_thr");
1083 int const result = ACE_Thread::resume (td->thr_handle_);
1084 if (result == -1) {
1085 if (errno != ENOTSUP)
1086 this->thr_to_be_removed_.enqueue_tail (td);
1087 return -1;
1089 else {
1090 ACE_CLR_BITS (td->thr_state_, ACE_THR_SUSPENDED);
1091 return 0;
1096 ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor *td, int async_cancel)
1098 ACE_TRACE ("ACE_Thread_Manager::cancel_thr");
1099 // Must set the state first and then try to cancel the thread.
1100 ACE_SET_BITS (td->thr_state_, ACE_THR_CANCELLED);
1102 if (async_cancel != 0)
1103 // Note that this call only does something relevant if the OS
1104 // platform supports asynchronous thread cancellation. Otherwise,
1105 // it's a no-op.
1106 return ACE_Thread::cancel (td->thr_id_);
1108 return 0;
1112 ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor *td, int signum)
1114 ACE_TRACE ("ACE_Thread_Manager::kill_thr");
1116 ACE_thread_t tid = td->thr_id_;
1118 int const result = ACE_Thread::kill (tid, signum);
1120 if (result != 0)
1122 // Only remove a thread from us when there is a "real" error.
1123 if (errno != ENOTSUP)
1124 this->thr_to_be_removed_.enqueue_tail (td);
1126 return -1;
1129 return 0;
1132 // ------------------------------------------------------------------
1133 // Factor out some common behavior to simplify the following methods.
1134 #define ACE_EXECUTE_OP(OP, ARG) \
1135 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \
1136 ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \
1137 ACE_FIND (this->find_thread (t_id), ptr); \
1138 if (ptr == 0) \
1140 errno = ENOENT; \
1141 return -1; \
1143 int const result = OP (ptr, ARG); \
1144 ACE_Errno_Guard error (errno); \
1145 while (! this->thr_to_be_removed_.is_empty ()) { \
1146 ACE_Thread_Descriptor * td = 0; \
1147 this->thr_to_be_removed_.dequeue_head (td); \
1148 this->remove_thr (td, 1); \
1150 return result
1152 // Suspend a single thread.
1155 ACE_Thread_Manager::suspend (ACE_thread_t t_id)
1157 ACE_TRACE ("ACE_Thread_Manager::suspend");
1158 ACE_EXECUTE_OP (this->suspend_thr, 0);
1161 // Resume a single thread.
1164 ACE_Thread_Manager::resume (ACE_thread_t t_id)
1166 ACE_TRACE ("ACE_Thread_Manager::resume");
1167 ACE_EXECUTE_OP (this->resume_thr, 0);
1170 // Cancel a single thread.
1173 ACE_Thread_Manager::cancel (ACE_thread_t t_id, int async_cancel)
1175 ACE_TRACE ("ACE_Thread_Manager::cancel");
1176 ACE_EXECUTE_OP (this->cancel_thr, async_cancel);
1179 // Send a signal to a single thread.
1182 ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum)
1184 ACE_TRACE ("ACE_Thread_Manager::kill");
1185 ACE_EXECUTE_OP (this->kill_thr, signum);
1189 ACE_Thread_Manager::check_state (ACE_UINT32 state,
1190 ACE_thread_t id,
1191 int enable)
1193 ACE_TRACE ("ACE_Thread_Manager::check_state");
1194 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1196 ACE_UINT32 thr_state;
1198 int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
1200 // If we're checking the state of our thread, try to get the cached
1201 // value out of TSS to avoid lookup.
1202 if (self_check)
1204 ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
1205 if (desc == 0)
1206 return 0; // Always return false.
1207 thr_state = desc->thr_state_;
1209 else
1211 // Not calling from self, have to look it up from the list.
1212 ACE_FIND (this->find_thread (id), ptr);
1213 if (ptr == 0)
1214 return 0;
1215 thr_state = ptr->thr_state_;
1217 if (enable)
1218 return ACE_BIT_ENABLED (thr_state, state);
1220 return ACE_BIT_DISABLED (thr_state, state);
1223 // Test if a single thread has terminated.
1226 ACE_Thread_Manager::testterminate (ACE_thread_t t_id)
1228 ACE_TRACE ("ACE_Thread_Manager::testterminate");
1229 return this->check_state (ACE_THR_TERMINATED, t_id);
1232 // Test if a single thread is suspended.
1235 ACE_Thread_Manager::testsuspend (ACE_thread_t t_id)
1237 ACE_TRACE ("ACE_Thread_Manager::testsuspend");
1238 return this->check_state (ACE_THR_SUSPENDED, t_id);
1241 // Test if a single thread is active (i.e., resumed).
1244 ACE_Thread_Manager::testresume (ACE_thread_t t_id)
1246 ACE_TRACE ("ACE_Thread_Manager::testresume");
1247 return this->check_state (ACE_THR_SUSPENDED, t_id, 0);
1250 // Test if a single thread is cancelled.
1253 ACE_Thread_Manager::testcancel (ACE_thread_t t_id)
1255 ACE_TRACE ("ACE_Thread_Manager::testcancel");
1256 return this->check_state (ACE_THR_CANCELLED, t_id);
1259 // Thread information query functions.
1262 ACE_Thread_Manager::hthread_within (ACE_hthread_t handle)
1264 ACE_TRACE ("ACE_Thread_Manager::hthread_within");
1265 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
1267 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1268 !iter.done ();
1269 iter.advance ())
1271 if (ACE_OS::thr_cmp(iter.next ()->thr_handle_, handle))
1273 return 1;
1277 return 0;
1281 ACE_Thread_Manager::thread_within (ACE_thread_t tid)
1283 ACE_TRACE ("ACE_Thread_Manager::thread_within");
1284 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
1286 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1287 !iter.done ();
1288 iter.advance ())
1290 if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid))
1292 return 1;
1296 return 0;
1299 // Get group ids for a particular thread id.
1302 ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id)
1304 ACE_TRACE ("ACE_Thread_Manager::get_grp");
1305 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1307 ACE_FIND (this->find_thread (t_id), ptr);
1309 if (ptr)
1310 grp_id = ptr->grp_id_;
1311 else
1312 return -1;
1313 return 0;
1316 // Set group ids for a particular thread id.
1319 ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id)
1321 ACE_TRACE ("ACE_Thread_Manager::set_grp");
1322 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1324 ACE_FIND (this->find_thread (t_id), ptr);
1325 if (ptr)
1326 ptr->grp_id_ = grp_id;
1327 else
1328 return -1;
1329 return 0;
1332 // Suspend a group of threads.
1335 ACE_Thread_Manager::apply_grp (int grp_id,
1336 ACE_THR_MEMBER_FUNC func,
1337 int arg)
1339 ACE_TRACE ("ACE_Thread_Manager::apply_grp");
1340 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1));
1341 ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
1343 int result = 0;
1345 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1346 !iter.done ();
1347 iter.advance ())
1349 if (iter.next ()->grp_id_ == grp_id)
1351 if ((this->*func) (iter.next (), arg) == -1)
1353 result = -1;
1358 // Must remove threads after we have traversed the thr_list_ to
1359 // prevent clobber thr_list_'s integrity.
1361 if (! this->thr_to_be_removed_.is_empty ())
1363 // Save/restore errno.
1364 ACE_Errno_Guard error (errno);
1366 for (ACE_Thread_Descriptor *td;
1367 this->thr_to_be_removed_.dequeue_head (td) != -1;
1369 this->remove_thr (td, 1);
1372 return result;
1376 ACE_Thread_Manager::suspend_grp (int grp_id)
1378 ACE_TRACE ("ACE_Thread_Manager::suspend_grp");
1379 return this->apply_grp (grp_id,
1380 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
1383 // Resume a group of threads.
1386 ACE_Thread_Manager::resume_grp (int grp_id)
1388 ACE_TRACE ("ACE_Thread_Manager::resume_grp");
1389 return this->apply_grp (grp_id,
1390 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
1393 // Kill a group of threads.
1396 ACE_Thread_Manager::kill_grp (int grp_id, int signum)
1398 ACE_TRACE ("ACE_Thread_Manager::kill_grp");
1399 return this->apply_grp (grp_id,
1400 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr), signum);
1403 // Cancel a group of threads.
1406 ACE_Thread_Manager::cancel_grp (int grp_id, int async_cancel)
1408 ACE_TRACE ("ACE_Thread_Manager::cancel_grp");
1409 return this->apply_grp (grp_id,
1410 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
1411 async_cancel);
1415 ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func, int arg)
1417 ACE_TRACE ("ACE_Thread_Manager::apply_all");
1418 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1419 ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
1421 int result = 0;
1423 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1424 !iter.done ();
1425 iter.advance ())
1427 if ((this->*func)(iter.next (), arg) == -1)
1429 result = -1;
1433 // Must remove threads after we have traversed the thr_list_ to
1434 // prevent clobber thr_list_'s integrity.
1436 if (! this->thr_to_be_removed_.is_empty ())
1438 // Save/restore errno.
1439 ACE_Errno_Guard error (errno);
1441 for (ACE_Thread_Descriptor *td;
1442 this->thr_to_be_removed_.dequeue_head (td) != -1;
1444 this->remove_thr (td, 1);
1447 return result;
1450 // Resume all threads that are suspended.
1453 ACE_Thread_Manager::resume_all (void)
1455 ACE_TRACE ("ACE_Thread_Manager::resume_all");
1456 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
1460 ACE_Thread_Manager::suspend_all (void)
1462 ACE_TRACE ("ACE_Thread_Manager::suspend_all");
1463 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
1467 ACE_Thread_Manager::kill_all (int sig)
1469 ACE_TRACE ("ACE_Thread_Manager::kill_all");
1470 return this->apply_all (&ACE_Thread_Manager::kill_thr, sig);
1474 ACE_Thread_Manager::cancel_all (int async_cancel)
1476 ACE_TRACE ("ACE_Thread_Manager::cancel_all");
1477 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
1478 async_cancel);
1482 ACE_Thread_Manager::join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status)
1484 ACE_TRACE ("ACE_Thread_Manager::join");
1486 bool found = false;
1487 ACE_Thread_Descriptor_Base tdb;
1490 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1492 #if !defined (ACE_HAS_VXTHREADS)
1493 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
1494 !biter.done ();
1495 biter.advance ())
1497 if (ACE_OS::thr_equal (biter.next ()->thr_id_, tid))
1499 ACE_Thread_Descriptor_Base *tdbl = biter.advance_and_remove (false);
1500 #ifndef ACE_LACKS_PTHREAD_JOIN
1501 if (ACE_Thread::join (tdbl->thr_handle_, status) == -1)
1503 return -1;
1505 #endif
1506 delete tdbl;
1508 // return immediately if we've found the thread we want to join.
1509 return 0;
1512 #endif /* !ACE_HAS_VXTHREADS */
1514 typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t;
1515 for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ())
1517 // If threads are created as THR_DETACHED or THR_DAEMON, we
1518 // can't help much.
1519 if (ACE_OS::thr_equal (iter.next ()->thr_id_,tid) &&
1520 (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
1521 || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
1523 tdb = *iter.next ();
1524 ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
1525 found = true;
1526 break;
1530 if (!found)
1531 return -1;
1532 // Didn't find the thread we want or the thread is not joinable.
1534 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1535 ACE_UNUSED_ARG (status); // not currently supported without pthread_join
1537 while (found)
1539 if (this->join_cond_.wait () == -1)
1540 return -1;
1542 found = false;
1543 for (iter_t iter (this->thr_list_); !iter.done () && !found; iter.advance ())
1544 if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid) &&
1545 (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
1546 || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
1547 found = true;
1550 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1554 #ifndef ACE_LACKS_PTHREAD_JOIN
1555 if (ACE_Thread::join (tdb.thr_handle_, status) == -1)
1556 return -1;
1557 #endif
1559 return 0;
1562 // Wait for group of threads
1565 ACE_Thread_Manager::wait_grp (int grp_id)
1567 ACE_TRACE ("ACE_Thread_Manager::wait_grp");
1569 int copy_count = 0;
1570 ACE_Thread_Descriptor_Base *copy_table = 0;
1572 // We have to make sure that while we wait for these threads to
1573 // exit, we do not have the lock. Therefore we make a copy of all
1574 // interesting entries and let go of the lock.
1576 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1578 #if !defined (ACE_HAS_VXTHREADS)
1579 ACE_NEW_RETURN (copy_table,
1580 ACE_Thread_Descriptor_Base [this->thr_list_.size ()
1581 + this->terminated_thr_list_.size ()],
1582 -1);
1583 #else
1584 ACE_NEW_RETURN (copy_table,
1585 ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
1586 -1);
1587 #endif /* !ACE_HAS_VXTHREADS */
1589 typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t;
1590 for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ())
1592 // If threads are created as THR_DETACHED or THR_DAEMON, we
1593 // can't help much.
1594 if (iter.next ()->grp_id_ == grp_id &&
1595 (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON)
1596 || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
1598 ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
1599 copy_table[copy_count++] = *iter.next ();
1603 #if !defined (ACE_HAS_VXTHREADS)
1604 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_);
1605 !biter.done ();
1606 biter.advance ())
1608 // If threads are created as THR_DETACHED or THR_DAEMON, we
1609 // can't help much.
1610 if (biter.next ()->grp_id_ == grp_id)
1612 ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (false);
1613 copy_table[copy_count++] = *tdb;
1614 delete tdb;
1617 #endif /* !ACE_HAS_VXTHREADS */
1619 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1621 while (copy_count)
1623 if (this->join_cond_.wait () == -1)
1625 delete[] copy_table;
1626 return -1;
1629 copy_count = 0;
1630 for (iter_t iter (this->thr_list_); !iter.done () && !copy_count; iter.advance ())
1631 if (iter.next ()->grp_id_ == grp_id &&
1632 ACE_BIT_ENABLED (iter.next ()->thr_state_, ACE_THR_JOINING) &&
1633 (ACE_BIT_DISABLED (iter.next ()->flags_,
1634 THR_DETACHED | THR_DAEMON)
1635 || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
1636 ++copy_count;
1639 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1642 // Now actually join() with all the threads in this group.
1643 int result = 0;
1645 for (int i = 0;
1646 i < copy_count && result != -1;
1647 i++)
1649 if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
1650 result = -1;
1653 delete [] copy_table;
1655 return result;
1658 // Must be called when thread goes out of scope to clean up its table
1659 // slot.
1661 ACE_THR_FUNC_RETURN
1662 ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status, bool do_thread_exit)
1664 ACE_TRACE ("ACE_Thread_Manager::exit");
1665 #if defined (ACE_WIN32)
1666 // Remove detached thread handle.
1668 if (do_thread_exit)
1670 #if 0
1671 // @@ This callback is now taken care of by TSS_Cleanup. Do we
1672 // need it anymore?
1674 // On Win32, if we really wants to exit from a thread, we must
1675 // first clean up the thread specific storage. By doing so,
1676 // ACE_Thread_Manager::exit will be called again with
1677 // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not
1678 // exiting the thread.) After the following call returns, we
1679 // are safe to exit this thread.
1680 delete ACE_Thread_Exit::instance ();
1681 #endif /* 0 */
1682 ACE_Thread::exit (status);
1684 #endif /* ACE_WIN32 */
1686 // Just hold onto the guard while finding this thread's id and
1688 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
1690 // Find the thread id, but don't use the cache. It might have been
1691 // deleted already.
1692 ACE_thread_t const id = ACE_OS::thr_self ();
1693 ACE_Thread_Descriptor* td = this->find_thread (id);
1694 if (td != 0)
1696 // @@ We call Thread_Descriptor terminate this realize the cleanup
1697 // process itself.
1698 td->terminate();
1700 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1701 this->join_cond_.broadcast ();
1702 #endif
1706 if (do_thread_exit)
1708 ACE_Thread::exit (status);
1709 // On reasonable systems <ACE_Thread::exit> should not return.
1710 // However, due to horrible semantics with Win32 thread-specific
1711 // storage this call can return (don't ask...).
1714 return 0;
1717 // Wait for all the threads to exit.
1720 ACE_Thread_Manager::wait (const ACE_Time_Value *timeout,
1721 bool abandon_detached_threads,
1722 bool use_absolute_time)
1724 ACE_TRACE ("ACE_Thread_Manager::wait");
1726 ACE_Auto_Ptr<ACE_Time_Value> local_timeout;
1727 // Check to see if we're using absolute time or not.
1728 if (use_absolute_time == false && timeout != 0)
1730 // create time value duplicate (preserves time policy)
1731 local_timeout.reset (timeout->duplicate ());
1732 // convert time value to absolute time
1733 (*local_timeout) = local_timeout->to_absolute_time ();
1734 // replace original time by abs time duplicate
1735 timeout = local_timeout.get ();
1738 #if !defined (ACE_HAS_VXTHREADS)
1739 ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> term_thr_list_copy;
1740 #endif /* ACE_HAS_VXTHREADS */
1742 #if defined (ACE_HAS_THREADS)
1744 // Just hold onto the guard while waiting.
1745 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1747 if (ACE_Object_Manager::shutting_down () != 1)
1749 // Program is not shutting down. Perform a normal wait on threads.
1750 if (abandon_detached_threads != 0)
1752 ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
1753 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor>
1754 iter (this->thr_list_);
1755 !iter.done ();
1756 iter.advance ())
1758 if (ACE_BIT_ENABLED (iter.next ()->flags_,
1759 THR_DETACHED | THR_DAEMON)
1760 && ACE_BIT_DISABLED (iter.next ()->flags_, THR_JOINABLE))
1762 this->thr_to_be_removed_.enqueue_tail (iter.next ());
1763 ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING);
1767 if (! this->thr_to_be_removed_.is_empty ())
1769 ACE_Thread_Descriptor *td = 0;
1770 while (this->thr_to_be_removed_.dequeue_head (td) != -1)
1771 this->remove_thr (td, 1);
1775 while (this->thr_list_.size () > 0)
1776 if (this->zero_cond_.wait (timeout) == -1)
1777 return -1;
1779 else
1780 // Program is shutting down, no chance to wait on threads.
1781 // Therefore, we'll just remove threads from the list.
1782 this->remove_thr_all ();
1784 #if !defined (ACE_HAS_VXTHREADS)
1785 ACE_Thread_Descriptor_Base* item = 0;
1786 while ((item = this->terminated_thr_list_.delete_head ()) != 0)
1788 term_thr_list_copy.insert_tail (item);
1790 #endif /* ACE_HAS_VXTHREADS */
1791 // Release the guard, giving other threads a chance to run.
1794 #if !defined (ACE_HAS_VXTHREADS)
1795 // @@ VxWorks doesn't support thr_join (yet.) We are working
1796 // on our implementation. Chorus'es thr_join seems broken.
1797 ACE_Thread_Descriptor_Base *item = 0;
1799 while ((item = term_thr_list_copy.delete_head ()) != 0)
1801 #ifndef ACE_LACKS_PTHREAD_JOIN
1802 if (ACE_BIT_DISABLED (item->flags_, THR_DETACHED | THR_DAEMON)
1803 || ACE_BIT_ENABLED (item->flags_, THR_JOINABLE))
1804 // Detached handles shouldn't reached here.
1805 (void) ACE_Thread::join (item->thr_handle_);
1806 #endif
1807 delete item;
1810 #endif /* !ACE_HAS_VXTHREADS */
1811 #else
1812 ACE_UNUSED_ARG (timeout);
1813 ACE_UNUSED_ARG (abandon_detached_threads);
1814 #endif /* ACE_HAS_THREADS */
1816 return 0;
1820 ACE_Thread_Manager::apply_task (ACE_Task_Base *task,
1821 ACE_THR_MEMBER_FUNC func,
1822 int arg)
1824 ACE_TRACE ("ACE_Thread_Manager::apply_task");
1825 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1826 ACE_ASSERT (this->thr_to_be_removed_.is_empty ());
1828 int result = 0;
1830 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
1831 !iter.done ();
1832 iter.advance ())
1833 if (iter.next ()->task_ == task
1834 && (this->*func) (iter.next (), arg) == -1)
1835 result = -1;
1837 // Must remove threads after we have traversed the thr_list_ to
1838 // prevent clobber thr_list_'s integrity.
1840 if (! this->thr_to_be_removed_.is_empty ())
1842 // Save/restore errno.
1843 ACE_Errno_Guard error (errno);
1845 for (ACE_Thread_Descriptor *td = 0;
1846 this->thr_to_be_removed_.dequeue_head (td) != -1;
1848 this->remove_thr (td, 1);
1851 return result;
1854 // Wait for all threads to exit a task.
1857 ACE_Thread_Manager::wait_task (ACE_Task_Base *task)
1859 int copy_count = 0;
1860 ACE_Thread_Descriptor_Base *copy_table = 0;
1862 // We have to make sure that while we wait for these threads to
1863 // exit, we do not have the lock. Therefore we make a copy of all
1864 // interesting entries and let go of the lock.
1866 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
1868 #if !defined (ACE_HAS_VXTHREADS)
1869 ACE_NEW_RETURN (copy_table,
1870 ACE_Thread_Descriptor_Base [this->thr_list_.size ()
1871 + this->terminated_thr_list_.size ()],
1872 -1);
1873 #else
1874 ACE_NEW_RETURN (copy_table,
1875 ACE_Thread_Descriptor_Base [this->thr_list_.size ()],
1876 -1);
1877 #endif /* !ACE_HAS_VXTHREADS */
1879 typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t;
1880 for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ())
1882 // If threads are created as THR_DETACHED or THR_DAEMON, we
1883 // can't wait on them here.
1884 if (iter.next ()->task_ == task &&
1885 (ACE_BIT_DISABLED (iter.next ()->flags_,
1886 THR_DETACHED | THR_DAEMON)
1887 || ACE_BIT_ENABLED (iter.next ()->flags_,
1888 THR_JOINABLE)))
1890 # ifdef ACE_LACKS_PTHREAD_JOIN
1891 if (ACE_OS::thr_equal (iter.next ()->thr_id_, ACE_OS::thr_self ()))
1893 errno = EDEADLK;
1894 delete[] copy_table;
1895 return -1;
1897 # endif
1898 ACE_SET_BITS (iter.next ()->thr_state_,
1899 ACE_THR_JOINING);
1900 copy_table[copy_count++] = *iter.next ();
1904 #if !defined (ACE_HAS_VXTHREADS)
1905 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> titer (this->terminated_thr_list_);
1906 !titer.done ();
1907 titer.advance ())
1909 // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here.
1910 if (titer.next ()->task_ == task)
1912 ACE_Thread_Descriptor_Base *tdb = titer.advance_and_remove (false);
1913 # ifndef ACE_LACKS_PTHREAD_JOIN
1914 copy_table[copy_count++] = *tdb;
1915 # endif
1916 delete tdb;
1919 #endif /* !ACE_HAS_VXTHREADS */
1921 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1923 while (copy_count)
1925 if (this->join_cond_.wait () == -1)
1927 delete[] copy_table;
1928 return -1;
1931 copy_count = 0;
1932 for (iter_t iter (this->thr_list_); !iter.done () && !copy_count; iter.advance ())
1933 if (iter.next ()->task_ == task &&
1934 ACE_BIT_ENABLED (iter.next ()->thr_state_, ACE_THR_JOINING) &&
1935 (ACE_BIT_DISABLED (iter.next ()->flags_,
1936 THR_DETACHED | THR_DAEMON)
1937 || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE)))
1938 ++copy_count;
1941 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1944 // Now to do the actual work
1945 int result = 0;
1947 for (int i = 0;
1948 i < copy_count && result != -1;
1949 i++)
1951 if (ACE_Thread::join (copy_table[i].thr_handle_) == -1)
1952 result = -1;
1955 delete [] copy_table;
1957 return result;
1960 // Suspend a task
1963 ACE_Thread_Manager::suspend_task (ACE_Task_Base *task)
1965 ACE_TRACE ("ACE_Thread_Manager::suspend_task");
1966 return this->apply_task (task,
1967 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr));
1970 // Resume a task.
1972 ACE_Thread_Manager::resume_task (ACE_Task_Base *task)
1974 ACE_TRACE ("ACE_Thread_Manager::resume_task");
1975 return this->apply_task (task,
1976 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr));
1979 // Kill a task.
1982 ACE_Thread_Manager::kill_task (ACE_Task_Base *task, int /* signum */)
1984 ACE_TRACE ("ACE_Thread_Manager::kill_task");
1985 return this->apply_task (task,
1986 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr));
1989 // Cancel a task.
1991 ACE_Thread_Manager::cancel_task (ACE_Task_Base *task,
1992 int async_cancel)
1994 ACE_TRACE ("ACE_Thread_Manager::cancel_task");
1995 return this->apply_task (task,
1996 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr),
1997 async_cancel);
2000 // Locate the index in the table associated with <task> from the
2001 // beginning of the table up to an index. Must be called with the
2002 // lock held.
2004 ACE_Thread_Descriptor *
2005 ACE_Thread_Manager::find_task (ACE_Task_Base *task, size_t slot)
2007 ACE_TRACE ("ACE_Thread_Manager::find_task");
2009 size_t i = 0;
2011 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2012 !iter.done ();
2013 iter.advance ())
2015 if (i >= slot)
2016 break;
2018 if (task == iter.next ()->task_)
2019 return iter.next ();
2021 ++i;
2024 return 0;
2027 // Returns the number of ACE_Task in a group.
2030 ACE_Thread_Manager::num_tasks_in_group (int grp_id)
2032 ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group");
2033 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2035 int tasks_count = 0;
2036 size_t i = 0;
2038 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2039 !iter.done ();
2040 iter.advance ())
2042 if (iter.next ()->grp_id_ == grp_id
2043 && this->find_task (iter.next ()->task_, i) == 0
2044 && iter.next ()->task_ != 0)
2046 ++tasks_count;
2049 ++i;
2051 return tasks_count;
2054 // Returns the number of threads in an ACE_Task.
2057 ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base *task)
2059 ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task");
2060 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2062 int threads_count = 0;
2064 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2065 !iter.done ();
2066 iter.advance ())
2068 if (iter.next ()->task_ == task)
2070 ++threads_count;
2074 return threads_count;
2077 // Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager.
2079 ssize_t
2080 ACE_Thread_Manager::task_all_list (ACE_Task_Base *task_list[],
2081 size_t n)
2083 ACE_TRACE ("ACE_Thread_Manager::task_all_list");
2084 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2086 size_t task_list_count = 0;
2088 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2089 !iter.done ();
2090 iter.advance ())
2092 if (task_list_count >= n)
2094 break;
2097 ACE_Task_Base *task_p = iter.next ()->task_;
2099 if (0 != task_p)
2101 // This thread has a task pointer; see if it's already in the
2102 // list. Don't add duplicates.
2103 size_t i = 0;
2105 for (; i < task_list_count; ++i)
2107 if (task_list[i] == task_p)
2109 break;
2113 if (i == task_list_count) // No match - add this one
2115 task_list[task_list_count++] = task_p;
2120 return ACE_Utils::truncate_cast<ssize_t> (task_list_count);
2123 // Returns in thread_list a list of all thread ids
2125 ssize_t
2126 ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list[],
2127 size_t n)
2129 ACE_TRACE ("ACE_Thread_Manager::thread_all_list");
2130 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2132 size_t thread_count = 0;
2134 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2135 !iter.done ();
2136 iter.advance ())
2138 if (thread_count >= n)
2140 break;
2143 thread_list[thread_count] = iter.next ()->thr_id_;
2144 ++thread_count;
2147 return ACE_Utils::truncate_cast<ssize_t> (thread_count);
2152 ACE_Thread_Manager::thr_state (ACE_thread_t id,
2153 ACE_UINT32& state)
2155 ACE_TRACE ("ACE_Thread_Manager::thr_state");
2156 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2158 int const self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ());
2160 // If we're checking the state of our thread, try to get the cached
2161 // value out of TSS to avoid lookup.
2162 if (self_check)
2164 ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc ();
2166 if (desc == 0)
2168 return 0; // Always return false.
2171 state = desc->thr_state_;
2173 else
2175 // Not calling from self, have to look it up from the list.
2176 ACE_FIND (this->find_thread (id), ptr);
2178 if (ptr == 0)
2180 return 0;
2183 state = ptr->thr_state_;
2186 return 1;
2189 // Returns in task_list a list of ACE_Tasks in a group.
2191 ssize_t
2192 ACE_Thread_Manager::task_list (int grp_id,
2193 ACE_Task_Base *task_list[],
2194 size_t n)
2196 ACE_TRACE ("ACE_Thread_Manager::task_list");
2197 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2199 ACE_Task_Base **task_list_iterator = task_list;
2200 size_t task_list_count = 0;
2201 size_t i = 0;
2203 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2204 !iter.done ();
2205 iter.advance ())
2207 if (task_list_count >= n)
2209 break;
2212 if (iter.next ()->grp_id_ == grp_id
2213 && this->find_task (iter.next ()->task_, i) == 0)
2215 task_list_iterator[task_list_count] = iter.next ()->task_;
2216 ++task_list_count;
2219 ++i;
2222 return ACE_Utils::truncate_cast<ssize_t> (task_list_count);
2225 // Returns in thread_list a list of thread ids in an ACE_Task.
2227 ssize_t
2228 ACE_Thread_Manager::thread_list (ACE_Task_Base *task,
2229 ACE_thread_t thread_list[],
2230 size_t n)
2232 ACE_TRACE ("ACE_Thread_Manager::thread_list");
2233 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2235 size_t thread_count = 0;
2237 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2238 !iter.done ();
2239 iter.advance ())
2241 if (thread_count >= n)
2243 break;
2246 if (iter.next ()->task_ == task)
2248 thread_list[thread_count] = iter.next ()->thr_id_;
2249 ++thread_count;
2253 return ACE_Utils::truncate_cast<ssize_t> (thread_count);
2256 // Returns in thread_list a list of thread handles in an ACE_Task.
2258 ssize_t
2259 ACE_Thread_Manager::hthread_list (ACE_Task_Base *task,
2260 ACE_hthread_t hthread_list[],
2261 size_t n)
2263 ACE_TRACE ("ACE_Thread_Manager::hthread_list");
2264 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2266 size_t hthread_count = 0;
2268 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2269 !iter.done ();
2270 iter.advance ())
2272 if (hthread_count >= n)
2274 break;
2277 if (iter.next ()->task_ == task)
2279 hthread_list[hthread_count] = iter.next ()->thr_handle_;
2280 ++hthread_count;
2284 return ACE_Utils::truncate_cast<ssize_t> (hthread_count);
2287 ssize_t
2288 ACE_Thread_Manager::thread_grp_list (int grp_id,
2289 ACE_thread_t thread_list[],
2290 size_t n)
2292 ACE_TRACE ("ACE_Thread_Manager::thread_grp_list");
2293 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2295 size_t thread_count = 0;
2297 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2298 !iter.done ();
2299 iter.advance ())
2301 if (thread_count >= n)
2303 break;
2306 if (iter.next ()->grp_id_ == grp_id)
2308 thread_list[thread_count] = iter.next ()->thr_id_;
2309 thread_count++;
2313 return ACE_Utils::truncate_cast<ssize_t> (thread_count);
2316 // Returns in thread_list a list of thread handles in an ACE_Task.
2318 ssize_t
2319 ACE_Thread_Manager::hthread_grp_list (int grp_id,
2320 ACE_hthread_t hthread_list[],
2321 size_t n)
2323 ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list");
2324 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2326 size_t hthread_count = 0;
2328 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2329 !iter.done ();
2330 iter.advance ())
2332 if (hthread_count >= n)
2334 break;
2337 if (iter.next ()->grp_id_ == grp_id)
2339 hthread_list[hthread_count] = iter.next ()->thr_handle_;
2340 hthread_count++;
2344 return ACE_Utils::truncate_cast<ssize_t> (hthread_count);
2348 ACE_Thread_Manager::set_grp (ACE_Task_Base *task, int grp_id)
2350 ACE_TRACE ("ACE_Thread_Manager::set_grp");
2351 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2353 for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_);
2354 !iter.done ();
2355 iter.advance ())
2357 if (iter.next ()->task_ == task)
2359 iter.next ()->grp_id_ = grp_id;
2363 return 0;
2367 ACE_Thread_Manager::get_grp (ACE_Task_Base *task, int &grp_id)
2369 ACE_TRACE ("ACE_Thread_Manager::get_grp");
2370 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
2372 ACE_FIND (this->find_task (task), ptr);
2373 grp_id = ptr->grp_id_;
2374 return 0;
2377 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Descriptor_Base);
2379 ACE_END_VERSIONED_NAMESPACE_DECL