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/Guard_T.h"
7 #include "ace/Time_Value.h"
8 #include "ace/OS_NS_sys_time.h"
9 #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 ()
23 ACE_At_Thread_Exit_Func::~ACE_At_Thread_Exit_Func ()
28 ACE_ALLOC_HOOK_DEFINE(ACE_At_Thread_Exit_Func
)
31 ACE_At_Thread_Exit_Func::apply ()
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;
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
;
61 ACE_Thread_Manager::dump ()
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_
);
78 iter
.next ()->dump ();
81 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
82 #endif /* ACE_HAS_DUMP */
85 ACE_Thread_Descriptor::~ACE_Thread_Descriptor ()
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_
;
102 // Do the apply method
103 at
->was_applied (true);
104 // Mark at has been applied to avoid double apply from
107 // If at is not owner delete at.
108 if (!at
->is_owner ())
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
);
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);
131 ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit
* cleanup
)
133 ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
138 this->at_push (cleanup
);
144 ACE_Thread_Descriptor::do_at_exit ()
146 ACE_TRACE ("ACE_Thread_Descriptor::do_at_exit");
147 while (at_exit_list_
!=0)
152 ACE_Thread_Descriptor::terminate ()
154 ACE_TRACE ("ACE_Thread_Descriptor::terminate");
158 ACE_Log_Msg
* log_msg
= this->log_msg_
;
162 // We must remove Thread_Descriptor from Thread_Manager list
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
182 #if defined (ACE_WIN32)
187 #endif /* ACE_WIN32 */
189 #endif /* !ACE_HAS_VXTHREADS */
191 // Remove thread descriptor from the table. 'this' is invalid
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.
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
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);
219 ACE_Thread_Descriptor::at_exit (void *object
,
220 ACE_CLEANUP_FUNC cleanup_hook
,
223 ACE_TRACE ("ACE_Thread_Descriptor::at_exit");
224 // To keep compatibility, when cleanup_hook is null really is a at_pop
226 if (cleanup_hook
== 0)
228 if (this->at_exit_list_
!= 0)
233 ACE_At_Thread_Exit
* cleanup
= 0;
234 ACE_NEW_RETURN (cleanup
,
235 ACE_At_Thread_Exit_Func (object
,
239 this->at_push (cleanup
);
245 ACE_Thread_Descriptor::dump () 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 ()
267 ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor");
268 ACE_NEW (this->sync_
,
269 ACE_DEFAULT_THREAD_MANAGER_LOCK
);
273 ACE_Thread_Descriptor::acquire_release ()
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
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.
294 ACE_Thread_Descriptor::acquire ()
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 ();
306 ACE_Thread_Descriptor::release ()
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
);
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
);
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 ();
360 // Initialize the synchronization variables.
362 ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc
,
368 #if defined (ACE_HAS_THREADS)
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_
)
377 ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
380 ACE_Thread_Manager::ACE_Thread_Manager (const ACE_Condition_Attributes
&attributes
,
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_
)
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)
404 ACE_Thread_Manager::instance ()
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_
,
419 ACE_Thread_Manager::delete_thr_mgr_
= true;
423 return ACE_Thread_Manager::thr_mgr_
;
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
;
442 ACE_Thread_Manager::close_singleton ()
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_
)
474 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
476 this->remove_thr_all ();
482 ACE_Thread_Manager::~ACE_Thread_Manager ()
484 ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager");
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)
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 ();
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
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
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
);
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
,
574 ACE_hthread_t
*t_handle
,
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
590 // Get a "new" Thread Descriptor from the freelist.
591 std::unique_ptr
<ACE_Thread_Descriptor
> new_thr_desc (this->thread_desc_freelist_
.remove ());
593 // Reset thread descriptor status
594 new_thr_desc
->reset (this);
596 ACE_Thread_Adapter
*thread_args
= 0;
597 # if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
598 ACE_NEW_RETURN (thread_args
,
599 ACE_Thread_Adapter (func
,
601 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
604 ACE_OS_Object_Manager::seh_except_selector(),
605 ACE_OS_Object_Manager::seh_except_handler(),
609 ACE_NEW_RETURN (thread_args
,
610 ACE_Thread_Adapter (func
,
612 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
617 # endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
618 std::unique_ptr
<ACE_Base_Thread_Adapter
> auto_thread_args (static_cast<ACE_Base_Thread_Adapter
*> (thread_args
));
620 ACE_TRACE ("ACE_Thread_Manager::spawn_i");
621 ACE_hthread_t thr_handle
;
627 // Acquire the <sync_> lock to block the spawned thread from
628 // removing this Thread Descriptor before it gets put into our
630 new_thr_desc
->sync_
->acquire ();
632 int const result
= ACE_Thread::spawn (func
,
645 // _Don't_ clobber errno here! result is either 0 or -1, and
646 // ACE_OS::thr_create () already set errno! D. Levine 28 Mar 1997
648 ACE_Errno_Guard
guard (errno
); // Lock release may smash errno
649 new_thr_desc
->sync_
->release ();
652 auto_thread_args
.release ();
654 #if defined (ACE_HAS_WTHREADS)
655 // Have to duplicate handle if client asks for it.
657 # if defined (ACE_LACKS_DUPLICATEHANDLE)
658 *t_handle
= thr_handle
;
659 # else /* ! ACE_LACKS_DUP */
660 (void) ::DuplicateHandle (::GetCurrentProcess (),
662 ::GetCurrentProcess (),
666 DUPLICATE_SAME_ACCESS
);
667 # endif /* ! ACE_LACKS_DUP */
668 #else /* ! ACE_HAS_WTHREADS */
670 *t_handle
= thr_handle
;
671 #endif /* ! ACE_HAS_WTHREADS */
673 // append_thr also put the <new_thr_desc> into Thread_Manager's
674 // double-linked list. Only after this point, can we manipulate
675 // double-linked list from a spawned thread's context.
676 return this->append_thr (*t_id
,
682 new_thr_desc
.release ());
686 ACE_Thread_Manager::spawn (ACE_THR_FUNC func
,
690 ACE_hthread_t
*t_handle
,
695 const char** thr_name
)
697 ACE_TRACE ("ACE_Thread_Manager::spawn");
699 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
702 grp_id
= this->grp_id_
++; // Increment the group id.
704 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
705 ACE_CLR_BITS (flags
, THR_INHERIT_SCHED
);
707 if (this->spawn_i (func
,
723 // Create N new threads running FUNC.
726 ACE_Thread_Manager::spawn_n (size_t n
,
733 ACE_hthread_t thread_handles
[],
736 const char* thr_name
[])
738 ACE_TRACE ("ACE_Thread_Manager::spawn_n");
739 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
742 grp_id
= this->grp_id_
++; // Increment the group id.
744 for (size_t i
= 0; i
< n
; i
++)
746 // @@ What should happen if this fails?! e.g., should we try to
747 // cancel the other threads that we've already spawned or what?
748 if (this->spawn_i (func
,
752 thread_handles
== 0 ? 0 : &thread_handles
[i
],
755 stack
== 0 ? 0 : stack
[i
],
756 stack_size
== 0 ? ACE_DEFAULT_THREAD_STACKSIZE
: stack_size
[i
],
758 thr_name
== 0 ? 0 : &thr_name
[i
]) == -1)
765 // Create N new threads running FUNC.
768 ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids
[],
777 ACE_hthread_t thread_handles
[],
779 const char* thr_name
[])
781 ACE_TRACE ("ACE_Thread_Manager::spawn_n");
782 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
785 grp_id
= this->grp_id_
++; // Increment the group id.
787 for (size_t i
= 0; i
< n
; i
++)
789 // @@ What should happen if this fails?! e.g., should we try to
790 // cancel the other threads that we've already spawned or what?
791 if (this->spawn_i (func
,
794 thread_ids
== 0 ? 0 : &thread_ids
[i
],
795 thread_handles
== 0 ? 0 : &thread_handles
[i
],
798 stack
== 0 ? 0 : stack
[i
],
799 stack_size
== 0 ? ACE_DEFAULT_THREAD_STACKSIZE
: stack_size
[i
],
801 thr_name
== 0 ? 0 : &thr_name
[i
]) == -1)
808 // Append a thread into the pool (does not check for duplicates).
809 // Must be called with locks held.
812 ACE_Thread_Manager::append_thr (ACE_thread_t t_id
,
813 ACE_hthread_t t_handle
,
814 ACE_UINT32 thr_state
,
818 ACE_Thread_Descriptor
*td
)
820 ACE_TRACE ("ACE_Thread_Manager::append_thr");
821 ACE_Thread_Descriptor
*thr_desc
= 0;
825 ACE_NEW_RETURN (thr_desc
,
826 ACE_Thread_Descriptor
,
828 thr_desc
->tm_
= this;
829 // Setup the Thread_Manager.
834 thr_desc
->thr_id_
= t_id
;
835 thr_desc
->thr_handle_
= t_handle
;
836 thr_desc
->grp_id_
= grp_id
;
837 thr_desc
->task_
= task
;
838 thr_desc
->flags_
= flags
;
840 this->thr_list_
.insert_head (thr_desc
);
841 ACE_SET_BITS (thr_desc
->thr_state_
, thr_state
);
842 thr_desc
->sync_
->release ();
847 // Return the thread descriptor (indexed by ACE_hthread_t).
849 ACE_Thread_Descriptor
*
850 ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id
)
852 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
856 if (ACE_OS::thr_cmp (iter
.next ()->thr_handle_
, h_id
))
865 // Locate the index in the table associated with <t_id>. Must be
866 // called with the lock held.
868 ACE_Thread_Descriptor
*
869 ACE_Thread_Manager::find_thread (ACE_thread_t t_id
)
871 ACE_TRACE ("ACE_Thread_Manager::find_thread");
873 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
877 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
, t_id
))
885 // Insert a thread into the pool (checks for duplicates and doesn't
886 // allow them to be inserted twice).
889 ACE_Thread_Manager::insert_thr (ACE_thread_t t_id
,
890 ACE_hthread_t t_handle
,
894 ACE_TRACE ("ACE_Thread_Manager::insert_thr");
895 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
897 // Check for duplicates and bail out if we're already registered...
898 if (this->find_thread (t_id
) != 0 )
902 grp_id
= this->grp_id_
++;
904 if (this->append_thr (t_id
,
915 // Run the registered hooks when the thread exits.
918 ACE_Thread_Manager::run_thread_exit_hooks (int i
)
920 #if 0 // currently unused!
921 ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks");
923 // @@ Currently, we have just one hook. This should clearly be
924 // generalized to support an arbitrary number of hooks.
926 ACE_Thread_Descriptor
*td
= this->thread_desc_self ();
927 for (ACE_Cleanup_Info_Node
*iter
= td
->cleanup_info_
->pop_front ();
929 iter
= cleanup_info_
->pop_front ())
931 if (iter
->cleanup_hook () != 0)
933 (*iter
->cleanup_hook ()) (iter
->object (), iter
->param ());
944 // Remove a thread from the pool. Must be called with locks held.
947 ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor
*td
,
950 ACE_TRACE ("ACE_Thread_Manager::remove_thr");
953 this->thr_list_
.remove (td
);
955 #if defined (ACE_WIN32)
956 if (close_handler
!= 0)
957 ::CloseHandle (td
->thr_handle_
);
959 ACE_UNUSED_ARG (close_handler
);
960 #endif /* ACE_WIN32 */
962 this->thread_desc_freelist_
.add (td
);
964 #if defined (ACE_HAS_THREADS)
965 // Tell all waiters when there are no more threads left in the pool.
966 if (this->thr_list_
.size () == 0)
967 this->zero_cond_
.broadcast ();
968 #endif /* ACE_HAS_THREADS */
971 // Repeatedly call remove_thr on all table entries until there
972 // is no thread left. Must be called with lock held.
974 ACE_Thread_Manager::remove_thr_all ()
976 ACE_Thread_Descriptor
*td
= 0;
978 while ((td
= this->thr_list_
.delete_head ()) != 0)
980 this->remove_thr (td
, 1);
984 // ------------------------------------------------------------------
985 // Factor out some common behavior to simplify the following methods.
986 #define ACE_THR_OP(OP,STATE) \
987 int result = OP (td->thr_handle_); \
988 if (result == -1) { \
989 if (errno != ENOTSUP) \
990 this->thr_to_be_removed_.enqueue_tail (td); \
994 ACE_SET_BITS (td->thr_state_, STATE); \
999 ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor
*td
, int)
1001 ACE_TRACE ("ACE_Thread_Manager::join_thr");
1003 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1004 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1006 if (ACE_BIT_DISABLED (td
->flags_
, THR_DETACHED
| THR_DAEMON
)
1007 || ACE_BIT_ENABLED (td
->flags_
, THR_JOINABLE
))
1009 if (td
->terminated_
)
1011 ACE_SET_BITS (td
->thr_state_
, ACE_THR_JOINING
);
1019 const ACE_thread_t waiting_id
= td
->thr_id_
;
1023 if (this->join_cond_
.wait () == -1)
1027 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1028 !iter
.done () && !found
; iter
.advance ())
1029 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
, waiting_id
))
1036 int const result
= ACE_Thread::join (td
->thr_handle_
);
1039 // Since the thread are being joined, we should
1040 // let it remove itself from the list.
1042 // this->remove_thr (td);
1046 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1052 ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor
*td
, int)
1054 ACE_TRACE ("ACE_Thread_Manager::suspend_thr");
1056 int const result
= ACE_Thread::suspend (td
->thr_handle_
);
1058 if (errno
!= ENOTSUP
)
1059 this->thr_to_be_removed_
.enqueue_tail (td
);
1063 ACE_SET_BITS (td
->thr_state_
, ACE_THR_SUSPENDED
);
1069 ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor
*td
, int)
1071 ACE_TRACE ("ACE_Thread_Manager::resume_thr");
1073 int const result
= ACE_Thread::resume (td
->thr_handle_
);
1075 if (errno
!= ENOTSUP
)
1076 this->thr_to_be_removed_
.enqueue_tail (td
);
1080 ACE_CLR_BITS (td
->thr_state_
, ACE_THR_SUSPENDED
);
1086 ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor
*td
, int async_cancel
)
1088 ACE_TRACE ("ACE_Thread_Manager::cancel_thr");
1089 // Must set the state first and then try to cancel the thread.
1090 ACE_SET_BITS (td
->thr_state_
, ACE_THR_CANCELLED
);
1092 if (async_cancel
!= 0)
1093 // Note that this call only does something relevant if the OS
1094 // platform supports asynchronous thread cancellation. Otherwise,
1096 return ACE_Thread::cancel (td
->thr_id_
);
1102 ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor
*td
, int signum
)
1104 ACE_TRACE ("ACE_Thread_Manager::kill_thr");
1106 ACE_thread_t tid
= td
->thr_id_
;
1108 int const result
= ACE_Thread::kill (tid
, signum
);
1112 // Only remove a thread from us when there is a "real" error.
1113 if (errno
!= ENOTSUP
)
1114 this->thr_to_be_removed_
.enqueue_tail (td
);
1122 // ------------------------------------------------------------------
1123 // Factor out some common behavior to simplify the following methods.
1124 #define ACE_EXECUTE_OP(OP, ARG) \
1125 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \
1126 ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \
1127 ACE_FIND (this->find_thread (t_id), ptr); \
1133 int const result = OP (ptr, ARG); \
1134 ACE_Errno_Guard error (errno); \
1135 while (! this->thr_to_be_removed_.is_empty ()) { \
1136 ACE_Thread_Descriptor * td = 0; \
1137 this->thr_to_be_removed_.dequeue_head (td); \
1138 this->remove_thr (td, 1); \
1142 // Suspend a single thread.
1145 ACE_Thread_Manager::suspend (ACE_thread_t t_id
)
1147 ACE_TRACE ("ACE_Thread_Manager::suspend");
1148 ACE_EXECUTE_OP (this->suspend_thr
, 0);
1151 // Resume a single thread.
1154 ACE_Thread_Manager::resume (ACE_thread_t t_id
)
1156 ACE_TRACE ("ACE_Thread_Manager::resume");
1157 ACE_EXECUTE_OP (this->resume_thr
, 0);
1160 // Cancel a single thread.
1163 ACE_Thread_Manager::cancel (ACE_thread_t t_id
, int async_cancel
)
1165 ACE_TRACE ("ACE_Thread_Manager::cancel");
1166 ACE_EXECUTE_OP (this->cancel_thr
, async_cancel
);
1169 // Send a signal to a single thread.
1172 ACE_Thread_Manager::kill (ACE_thread_t t_id
, int signum
)
1174 ACE_TRACE ("ACE_Thread_Manager::kill");
1175 ACE_EXECUTE_OP (this->kill_thr
, signum
);
1179 ACE_Thread_Manager::check_state (ACE_UINT32 state
,
1183 ACE_TRACE ("ACE_Thread_Manager::check_state");
1184 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1186 ACE_UINT32 thr_state
;
1188 int self_check
= ACE_OS::thr_equal (id
, ACE_OS::thr_self ());
1190 // If we're checking the state of our thread, try to get the cached
1191 // value out of TSS to avoid lookup.
1194 ACE_Thread_Descriptor
*desc
= ACE_LOG_MSG
->thr_desc ();
1196 return 0; // Always return false.
1197 thr_state
= desc
->thr_state_
;
1201 // Not calling from self, have to look it up from the list.
1202 ACE_FIND (this->find_thread (id
), ptr
);
1205 thr_state
= ptr
->thr_state_
;
1208 return ACE_BIT_ENABLED (thr_state
, state
);
1210 return ACE_BIT_DISABLED (thr_state
, state
);
1213 // Test if a single thread has terminated.
1216 ACE_Thread_Manager::testterminate (ACE_thread_t t_id
)
1218 ACE_TRACE ("ACE_Thread_Manager::testterminate");
1219 return this->check_state (ACE_THR_TERMINATED
, t_id
);
1222 // Test if a single thread is suspended.
1225 ACE_Thread_Manager::testsuspend (ACE_thread_t t_id
)
1227 ACE_TRACE ("ACE_Thread_Manager::testsuspend");
1228 return this->check_state (ACE_THR_SUSPENDED
, t_id
);
1231 // Test if a single thread is active (i.e., resumed).
1234 ACE_Thread_Manager::testresume (ACE_thread_t t_id
)
1236 ACE_TRACE ("ACE_Thread_Manager::testresume");
1237 return this->check_state (ACE_THR_SUSPENDED
, t_id
, 0);
1240 // Test if a single thread is cancelled.
1243 ACE_Thread_Manager::testcancel (ACE_thread_t t_id
)
1245 ACE_TRACE ("ACE_Thread_Manager::testcancel");
1246 return this->check_state (ACE_THR_CANCELLED
, t_id
);
1249 // Thread information query functions.
1252 ACE_Thread_Manager::hthread_within (ACE_hthread_t handle
)
1254 ACE_TRACE ("ACE_Thread_Manager::hthread_within");
1255 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_monx
, this->lock_
, -1));
1257 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1261 if (ACE_OS::thr_cmp(iter
.next ()->thr_handle_
, handle
))
1271 ACE_Thread_Manager::thread_within (ACE_thread_t tid
)
1273 ACE_TRACE ("ACE_Thread_Manager::thread_within");
1274 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_monx
, this->lock_
, -1));
1276 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1280 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
, tid
))
1289 // Get group ids for a particular thread id.
1292 ACE_Thread_Manager::get_grp (ACE_thread_t t_id
, int &grp_id
)
1294 ACE_TRACE ("ACE_Thread_Manager::get_grp");
1295 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1297 ACE_FIND (this->find_thread (t_id
), ptr
);
1300 grp_id
= ptr
->grp_id_
;
1306 // Set group ids for a particular thread id.
1309 ACE_Thread_Manager::set_grp (ACE_thread_t t_id
, int grp_id
)
1311 ACE_TRACE ("ACE_Thread_Manager::set_grp");
1312 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1314 ACE_FIND (this->find_thread (t_id
), ptr
);
1316 ptr
->grp_id_
= grp_id
;
1322 // Suspend a group of threads.
1325 ACE_Thread_Manager::apply_grp (int grp_id
,
1326 ACE_THR_MEMBER_FUNC func
,
1329 ACE_TRACE ("ACE_Thread_Manager::apply_grp");
1330 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_monx
, this->lock_
, -1));
1331 ACE_ASSERT (this->thr_to_be_removed_
.is_empty ());
1335 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1339 if (iter
.next ()->grp_id_
== grp_id
)
1341 if ((this->*func
) (iter
.next (), arg
) == -1)
1348 // Must remove threads after we have traversed the thr_list_ to
1349 // prevent clobber thr_list_'s integrity.
1351 if (! this->thr_to_be_removed_
.is_empty ())
1353 // Save/restore errno.
1354 ACE_Errno_Guard
error (errno
);
1356 for (ACE_Thread_Descriptor
*td
;
1357 this->thr_to_be_removed_
.dequeue_head (td
) != -1;
1359 this->remove_thr (td
, 1);
1366 ACE_Thread_Manager::suspend_grp (int grp_id
)
1368 ACE_TRACE ("ACE_Thread_Manager::suspend_grp");
1369 return this->apply_grp (grp_id
,
1370 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr
));
1373 // Resume a group of threads.
1376 ACE_Thread_Manager::resume_grp (int grp_id
)
1378 ACE_TRACE ("ACE_Thread_Manager::resume_grp");
1379 return this->apply_grp (grp_id
,
1380 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr
));
1383 // Kill a group of threads.
1386 ACE_Thread_Manager::kill_grp (int grp_id
, int signum
)
1388 ACE_TRACE ("ACE_Thread_Manager::kill_grp");
1389 return this->apply_grp (grp_id
,
1390 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr
), signum
);
1393 // Cancel a group of threads.
1396 ACE_Thread_Manager::cancel_grp (int grp_id
, int async_cancel
)
1398 ACE_TRACE ("ACE_Thread_Manager::cancel_grp");
1399 return this->apply_grp (grp_id
,
1400 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr
),
1405 ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func
, int arg
)
1407 ACE_TRACE ("ACE_Thread_Manager::apply_all");
1408 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1409 ACE_ASSERT (this->thr_to_be_removed_
.is_empty ());
1413 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1417 if ((this->*func
)(iter
.next (), arg
) == -1)
1423 // Must remove threads after we have traversed the thr_list_ to
1424 // prevent clobber thr_list_'s integrity.
1426 if (! this->thr_to_be_removed_
.is_empty ())
1428 // Save/restore errno.
1429 ACE_Errno_Guard
error (errno
);
1431 for (ACE_Thread_Descriptor
*td
;
1432 this->thr_to_be_removed_
.dequeue_head (td
) != -1;
1434 this->remove_thr (td
, 1);
1440 // Resume all threads that are suspended.
1443 ACE_Thread_Manager::resume_all ()
1445 ACE_TRACE ("ACE_Thread_Manager::resume_all");
1446 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr
));
1450 ACE_Thread_Manager::suspend_all ()
1452 ACE_TRACE ("ACE_Thread_Manager::suspend_all");
1453 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr
));
1457 ACE_Thread_Manager::kill_all (int sig
)
1459 ACE_TRACE ("ACE_Thread_Manager::kill_all");
1460 return this->apply_all (&ACE_Thread_Manager::kill_thr
, sig
);
1464 ACE_Thread_Manager::cancel_all (int async_cancel
)
1466 ACE_TRACE ("ACE_Thread_Manager::cancel_all");
1467 return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr
),
1472 ACE_Thread_Manager::join (ACE_thread_t tid
, ACE_THR_FUNC_RETURN
*status
)
1474 ACE_TRACE ("ACE_Thread_Manager::join");
1477 ACE_Thread_Descriptor_Base tdb
;
1480 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1482 #if !defined (ACE_HAS_VXTHREADS)
1483 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor_Base
> biter (this->terminated_thr_list_
);
1487 if (ACE_OS::thr_equal (biter
.next ()->thr_id_
, tid
))
1489 std::unique_ptr
<ACE_Thread_Descriptor_Base
> tdbl (biter
.advance_and_remove (false));
1491 #ifndef ACE_LACKS_PTHREAD_JOIN
1492 if (ACE_Thread::join (tdbl
->thr_handle_
, status
) == -1)
1498 // return immediately if we've found the thread we want to join.
1502 #endif /* !ACE_HAS_VXTHREADS */
1504 using iter_t
= ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
>;
1505 for (iter_t
iter (this->thr_list_
); !iter
.done (); iter
.advance ())
1507 // If threads are created as THR_DETACHED or THR_DAEMON, we
1509 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
,tid
) &&
1510 (ACE_BIT_DISABLED (iter
.next ()->flags_
, THR_DETACHED
| THR_DAEMON
)
1511 || ACE_BIT_ENABLED (iter
.next ()->flags_
, THR_JOINABLE
)))
1513 tdb
= *iter
.next ();
1514 ACE_SET_BITS (iter
.next ()->thr_state_
, ACE_THR_JOINING
);
1522 // Didn't find the thread we want or the thread is not joinable.
1524 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1525 ACE_UNUSED_ARG (status
); // not currently supported without pthread_join
1529 if (this->join_cond_
.wait () == -1)
1533 for (iter_t
iter (this->thr_list_
); !iter
.done () && !found
; iter
.advance ())
1534 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
, tid
) &&
1535 (ACE_BIT_DISABLED (iter
.next ()->flags_
, THR_DETACHED
| THR_DAEMON
)
1536 || ACE_BIT_ENABLED (iter
.next ()->flags_
, THR_JOINABLE
)))
1540 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1544 #ifndef ACE_LACKS_PTHREAD_JOIN
1545 if (ACE_Thread::join (tdb
.thr_handle_
, status
) == -1)
1552 // Wait for group of threads
1555 ACE_Thread_Manager::wait_grp (int grp_id
)
1557 ACE_TRACE ("ACE_Thread_Manager::wait_grp");
1560 ACE_Thread_Descriptor_Base
*copy_table
= 0;
1562 // We have to make sure that while we wait for these threads to
1563 // exit, we do not have the lock. Therefore we make a copy of all
1564 // interesting entries and let go of the lock.
1566 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1568 #if !defined (ACE_HAS_VXTHREADS)
1569 ACE_NEW_RETURN (copy_table
,
1570 ACE_Thread_Descriptor_Base
[this->thr_list_
.size ()
1571 + this->terminated_thr_list_
.size ()],
1574 ACE_NEW_RETURN (copy_table
,
1575 ACE_Thread_Descriptor_Base
[this->thr_list_
.size ()],
1577 #endif /* !ACE_HAS_VXTHREADS */
1579 using iter_t
= ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
>;
1580 for (iter_t
iter (this->thr_list_
); !iter
.done (); iter
.advance ())
1582 // If threads are created as THR_DETACHED or THR_DAEMON, we
1584 if (iter
.next ()->grp_id_
== grp_id
&&
1585 (ACE_BIT_DISABLED (iter
.next ()->flags_
, THR_DETACHED
| THR_DAEMON
)
1586 || ACE_BIT_ENABLED (iter
.next ()->flags_
, THR_JOINABLE
)))
1588 ACE_SET_BITS (iter
.next ()->thr_state_
, ACE_THR_JOINING
);
1589 copy_table
[copy_count
++] = *iter
.next ();
1593 #if !defined (ACE_HAS_VXTHREADS)
1594 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor_Base
> biter (this->terminated_thr_list_
);
1598 // If threads are created as THR_DETACHED or THR_DAEMON, we
1600 if (biter
.next ()->grp_id_
== grp_id
)
1602 ACE_Thread_Descriptor_Base
*tdb
= biter
.advance_and_remove (false);
1603 copy_table
[copy_count
++] = *tdb
;
1607 #endif /* !ACE_HAS_VXTHREADS */
1609 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1613 if (this->join_cond_
.wait () == -1)
1615 delete[] copy_table
;
1620 for (iter_t
iter (this->thr_list_
); !iter
.done () && !copy_count
; iter
.advance ())
1621 if (iter
.next ()->grp_id_
== grp_id
&&
1622 ACE_BIT_ENABLED (iter
.next ()->thr_state_
, ACE_THR_JOINING
) &&
1623 (ACE_BIT_DISABLED (iter
.next ()->flags_
,
1624 THR_DETACHED
| THR_DAEMON
)
1625 || ACE_BIT_ENABLED (iter
.next ()->flags_
, THR_JOINABLE
)))
1629 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1632 // Now actually join() with all the threads in this group.
1636 i
< copy_count
&& result
!= -1;
1639 if (ACE_Thread::join (copy_table
[i
].thr_handle_
) == -1)
1643 delete [] copy_table
;
1648 // Must be called when thread goes out of scope to clean up its table
1652 ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status
, bool do_thread_exit
)
1654 ACE_TRACE ("ACE_Thread_Manager::exit");
1655 #if defined (ACE_WIN32)
1656 // Remove detached thread handle.
1661 // @@ This callback is now taken care of by TSS_Cleanup. Do we
1664 // On Win32, if we really wants to exit from a thread, we must
1665 // first clean up the thread specific storage. By doing so,
1666 // ACE_Thread_Manager::exit will be called again with
1667 // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not
1668 // exiting the thread.) After the following call returns, we
1669 // are safe to exit this thread.
1670 delete ACE_Thread_Exit::instance ();
1672 ACE_Thread::exit (status
);
1674 #endif /* ACE_WIN32 */
1676 // Just hold onto the guard while finding this thread's id and
1678 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, 0));
1680 // Find the thread id, but don't use the cache. It might have been
1682 ACE_thread_t
const id
= ACE_OS::thr_self ();
1683 ACE_Thread_Descriptor
* td
= this->find_thread (id
);
1686 // @@ We call Thread_Descriptor terminate this realize the cleanup
1690 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1691 this->join_cond_
.broadcast ();
1698 ACE_Thread::exit (status
);
1699 // On reasonable systems <ACE_Thread::exit> should not return.
1700 // However, due to horrible semantics with Win32 thread-specific
1701 // storage this call can return (don't ask...).
1707 // Wait for all the threads to exit.
1709 ACE_Thread_Manager::wait (const ACE_Time_Value
*timeout
,
1710 bool abandon_detached_threads
,
1711 bool use_absolute_time
)
1713 ACE_TRACE ("ACE_Thread_Manager::wait");
1715 std::unique_ptr
<ACE_Time_Value
> local_timeout
;
1716 // Check to see if we're using absolute time or not.
1717 if (!use_absolute_time
&& timeout
!= 0)
1719 // create time value duplicate (preserves time policy)
1720 local_timeout
.reset (timeout
->duplicate ());
1721 // convert time value to absolute time
1722 (*local_timeout
) = local_timeout
->to_absolute_time ();
1723 // replace original time by abs time duplicate
1724 timeout
= local_timeout
.get ();
1727 #if !defined (ACE_HAS_VXTHREADS)
1728 ACE_Double_Linked_List
<ACE_Thread_Descriptor_Base
> term_thr_list_copy
;
1729 #endif /* ACE_HAS_VXTHREADS */
1731 #if defined (ACE_HAS_THREADS)
1733 // Just hold onto the guard while waiting.
1734 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1736 if (ACE_Object_Manager::shutting_down () != 1)
1738 // Program is not shutting down. Perform a normal wait on threads.
1739 if (abandon_detached_threads
!= 0)
1741 ACE_ASSERT (this->thr_to_be_removed_
.is_empty ());
1742 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
>
1743 iter (this->thr_list_
);
1747 if (ACE_BIT_ENABLED (iter
.next ()->flags_
,
1748 THR_DETACHED
| THR_DAEMON
)
1749 && ACE_BIT_DISABLED (iter
.next ()->flags_
, THR_JOINABLE
))
1751 this->thr_to_be_removed_
.enqueue_tail (iter
.next ());
1752 ACE_SET_BITS (iter
.next ()->thr_state_
, ACE_THR_JOINING
);
1756 if (! this->thr_to_be_removed_
.is_empty ())
1758 ACE_Thread_Descriptor
*td
= 0;
1759 while (this->thr_to_be_removed_
.dequeue_head (td
) != -1)
1760 this->remove_thr (td
, 1);
1764 while (this->thr_list_
.size () > 0)
1765 if (this->zero_cond_
.wait (timeout
) == -1)
1769 // Program is shutting down, no chance to wait on threads.
1770 // Therefore, we'll just remove threads from the list.
1771 this->remove_thr_all ();
1773 #if !defined (ACE_HAS_VXTHREADS)
1774 ACE_Thread_Descriptor_Base
* item
= 0;
1775 while ((item
= this->terminated_thr_list_
.delete_head ()) != 0)
1777 term_thr_list_copy
.insert_tail (item
);
1779 #endif /* ACE_HAS_VXTHREADS */
1780 // Release the guard, giving other threads a chance to run.
1783 #if !defined (ACE_HAS_VXTHREADS)
1784 // @@ VxWorks doesn't support thr_join (yet.) We are working
1785 // on our implementation.
1786 ACE_Thread_Descriptor_Base
*item
= 0;
1788 while ((item
= term_thr_list_copy
.delete_head ()) != 0)
1790 #ifndef ACE_LACKS_PTHREAD_JOIN
1791 if (ACE_BIT_DISABLED (item
->flags_
, THR_DETACHED
| THR_DAEMON
)
1792 || ACE_BIT_ENABLED (item
->flags_
, THR_JOINABLE
))
1793 // Detached handles shouldn't reached here.
1794 (void) ACE_Thread::join (item
->thr_handle_
);
1799 #endif /* !ACE_HAS_VXTHREADS */
1801 ACE_UNUSED_ARG (timeout
);
1802 ACE_UNUSED_ARG (abandon_detached_threads
);
1803 #endif /* ACE_HAS_THREADS */
1809 ACE_Thread_Manager::apply_task (ACE_Task_Base
*task
,
1810 ACE_THR_MEMBER_FUNC func
,
1813 ACE_TRACE ("ACE_Thread_Manager::apply_task");
1814 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1815 ACE_ASSERT (this->thr_to_be_removed_
.is_empty ());
1819 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
1822 if (iter
.next ()->task_
== task
1823 && (this->*func
) (iter
.next (), arg
) == -1)
1826 // Must remove threads after we have traversed the thr_list_ to
1827 // prevent clobber thr_list_'s integrity.
1829 if (! this->thr_to_be_removed_
.is_empty ())
1831 // Save/restore errno.
1832 ACE_Errno_Guard
error (errno
);
1834 for (ACE_Thread_Descriptor
*td
= 0;
1835 this->thr_to_be_removed_
.dequeue_head (td
) != -1;
1837 this->remove_thr (td
, 1);
1843 // Wait for all threads to exit a task.
1846 ACE_Thread_Manager::wait_task (ACE_Task_Base
*task
)
1849 ACE_Thread_Descriptor_Base
*copy_table
= 0;
1851 // We have to make sure that while we wait for these threads to
1852 // exit, we do not have the lock. Therefore we make a copy of all
1853 // interesting entries and let go of the lock.
1855 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
1857 #if !defined (ACE_HAS_VXTHREADS)
1858 ACE_NEW_RETURN (copy_table
,
1859 ACE_Thread_Descriptor_Base
[this->thr_list_
.size ()
1860 + this->terminated_thr_list_
.size ()],
1863 ACE_NEW_RETURN (copy_table
,
1864 ACE_Thread_Descriptor_Base
[this->thr_list_
.size ()],
1866 #endif /* !ACE_HAS_VXTHREADS */
1868 using iter_t
= ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
>;
1869 for (iter_t
iter (this->thr_list_
); !iter
.done (); iter
.advance ())
1871 // If threads are created as THR_DETACHED or THR_DAEMON, we
1872 // can't wait on them here.
1873 if (iter
.next ()->task_
== task
&&
1874 (ACE_BIT_DISABLED (iter
.next ()->flags_
,
1875 THR_DETACHED
| THR_DAEMON
)
1876 || ACE_BIT_ENABLED (iter
.next ()->flags_
,
1879 # ifdef ACE_LACKS_PTHREAD_JOIN
1880 if (ACE_OS::thr_equal (iter
.next ()->thr_id_
, ACE_OS::thr_self ()))
1883 delete[] copy_table
;
1887 ACE_SET_BITS (iter
.next ()->thr_state_
,
1889 copy_table
[copy_count
++] = *iter
.next ();
1893 #if !defined (ACE_HAS_VXTHREADS)
1894 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor_Base
> titer (this->terminated_thr_list_
);
1898 // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here.
1899 if (titer
.next ()->task_
== task
)
1901 ACE_Thread_Descriptor_Base
*tdb
= titer
.advance_and_remove (false);
1902 # ifndef ACE_LACKS_PTHREAD_JOIN
1903 copy_table
[copy_count
++] = *tdb
;
1908 #endif /* !ACE_HAS_VXTHREADS */
1910 #if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN)
1914 if (this->join_cond_
.wait () == -1)
1916 delete[] copy_table
;
1921 for (iter_t
iter (this->thr_list_
); !iter
.done () && !copy_count
; iter
.advance ())
1922 if (iter
.next ()->task_
== task
&&
1923 ACE_BIT_ENABLED (iter
.next ()->thr_state_
, ACE_THR_JOINING
) &&
1924 (ACE_BIT_DISABLED (iter
.next ()->flags_
,
1925 THR_DETACHED
| THR_DAEMON
)
1926 || ACE_BIT_ENABLED (iter
.next ()->flags_
, THR_JOINABLE
)))
1930 #endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN
1933 // Now to do the actual work
1937 i
< copy_count
&& result
!= -1;
1940 if (ACE_Thread::join (copy_table
[i
].thr_handle_
) == -1)
1944 delete [] copy_table
;
1952 ACE_Thread_Manager::suspend_task (ACE_Task_Base
*task
)
1954 ACE_TRACE ("ACE_Thread_Manager::suspend_task");
1955 return this->apply_task (task
,
1956 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr
));
1961 ACE_Thread_Manager::resume_task (ACE_Task_Base
*task
)
1963 ACE_TRACE ("ACE_Thread_Manager::resume_task");
1964 return this->apply_task (task
,
1965 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr
));
1971 ACE_Thread_Manager::kill_task (ACE_Task_Base
*task
, int /* signum */)
1973 ACE_TRACE ("ACE_Thread_Manager::kill_task");
1974 return this->apply_task (task
,
1975 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr
));
1980 ACE_Thread_Manager::cancel_task (ACE_Task_Base
*task
,
1983 ACE_TRACE ("ACE_Thread_Manager::cancel_task");
1984 return this->apply_task (task
,
1985 ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr
),
1989 // Locate the index in the table associated with <task> from the
1990 // beginning of the table up to an index. Must be called with the
1993 ACE_Thread_Descriptor
*
1994 ACE_Thread_Manager::find_task (ACE_Task_Base
*task
, size_t slot
)
1996 ACE_TRACE ("ACE_Thread_Manager::find_task");
2000 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2007 if (task
== iter
.next ()->task_
)
2008 return iter
.next ();
2016 // Returns the number of ACE_Task in a group.
2019 ACE_Thread_Manager::num_tasks_in_group (int grp_id
)
2021 ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group");
2022 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2024 int tasks_count
= 0;
2027 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2031 if (iter
.next ()->grp_id_
== grp_id
2032 && this->find_task (iter
.next ()->task_
, i
) == 0
2033 && iter
.next ()->task_
!= 0)
2043 // Returns the number of threads in an ACE_Task.
2046 ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base
*task
)
2048 ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task");
2049 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2051 int threads_count
= 0;
2053 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2057 if (iter
.next ()->task_
== task
)
2063 return threads_count
;
2066 // Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager.
2069 ACE_Thread_Manager::task_all_list (ACE_Task_Base
*task_list
[],
2072 ACE_TRACE ("ACE_Thread_Manager::task_all_list");
2073 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2075 size_t task_list_count
= 0;
2077 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2081 if (task_list_count
>= n
)
2086 ACE_Task_Base
*task_p
= iter
.next ()->task_
;
2090 // This thread has a task pointer; see if it's already in the
2091 // list. Don't add duplicates.
2094 for (; i
< task_list_count
; ++i
)
2096 if (task_list
[i
] == task_p
)
2102 if (i
== task_list_count
) // No match - add this one
2104 task_list
[task_list_count
++] = task_p
;
2109 return ACE_Utils::truncate_cast
<ssize_t
> (task_list_count
);
2112 // Returns in thread_list a list of all thread ids
2115 ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list
[],
2118 ACE_TRACE ("ACE_Thread_Manager::thread_all_list");
2119 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2121 size_t thread_count
= 0;
2123 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2127 if (thread_count
>= n
)
2132 thread_list
[thread_count
] = iter
.next ()->thr_id_
;
2136 return ACE_Utils::truncate_cast
<ssize_t
> (thread_count
);
2141 ACE_Thread_Manager::thr_state (ACE_thread_t id
,
2144 ACE_TRACE ("ACE_Thread_Manager::thr_state");
2145 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2147 int const self_check
= ACE_OS::thr_equal (id
, ACE_OS::thr_self ());
2149 // If we're checking the state of our thread, try to get the cached
2150 // value out of TSS to avoid lookup.
2153 ACE_Thread_Descriptor
*desc
= ACE_LOG_MSG
->thr_desc ();
2157 return 0; // Always return false.
2160 state
= desc
->thr_state_
;
2164 // Not calling from self, have to look it up from the list.
2165 ACE_FIND (this->find_thread (id
), ptr
);
2172 state
= ptr
->thr_state_
;
2178 // Returns in task_list a list of ACE_Tasks in a group.
2181 ACE_Thread_Manager::task_list (int grp_id
,
2182 ACE_Task_Base
*task_list
[],
2185 ACE_TRACE ("ACE_Thread_Manager::task_list");
2186 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2188 ACE_Task_Base
**task_list_iterator
= task_list
;
2189 size_t task_list_count
= 0;
2192 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2196 if (task_list_count
>= n
)
2201 if (iter
.next ()->grp_id_
== grp_id
2202 && this->find_task (iter
.next ()->task_
, i
) == 0)
2204 task_list_iterator
[task_list_count
] = iter
.next ()->task_
;
2211 return ACE_Utils::truncate_cast
<ssize_t
> (task_list_count
);
2214 // Returns in thread_list a list of thread ids in an ACE_Task.
2217 ACE_Thread_Manager::thread_list (ACE_Task_Base
*task
,
2218 ACE_thread_t thread_list
[],
2221 ACE_TRACE ("ACE_Thread_Manager::thread_list");
2222 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2224 size_t thread_count
= 0;
2226 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2230 if (thread_count
>= n
)
2235 if (iter
.next ()->task_
== task
)
2237 thread_list
[thread_count
] = iter
.next ()->thr_id_
;
2242 return ACE_Utils::truncate_cast
<ssize_t
> (thread_count
);
2245 // Returns in thread_list a list of thread handles in an ACE_Task.
2248 ACE_Thread_Manager::hthread_list (ACE_Task_Base
*task
,
2249 ACE_hthread_t hthread_list
[],
2252 ACE_TRACE ("ACE_Thread_Manager::hthread_list");
2253 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2255 size_t hthread_count
= 0;
2257 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2261 if (hthread_count
>= n
)
2266 if (iter
.next ()->task_
== task
)
2268 hthread_list
[hthread_count
] = iter
.next ()->thr_handle_
;
2273 return ACE_Utils::truncate_cast
<ssize_t
> (hthread_count
);
2277 ACE_Thread_Manager::thread_grp_list (int grp_id
,
2278 ACE_thread_t thread_list
[],
2281 ACE_TRACE ("ACE_Thread_Manager::thread_grp_list");
2282 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2284 size_t thread_count
= 0;
2286 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2290 if (thread_count
>= n
)
2295 if (iter
.next ()->grp_id_
== grp_id
)
2297 thread_list
[thread_count
] = iter
.next ()->thr_id_
;
2302 return ACE_Utils::truncate_cast
<ssize_t
> (thread_count
);
2305 // Returns in thread_list a list of thread handles in an ACE_Task.
2308 ACE_Thread_Manager::hthread_grp_list (int grp_id
,
2309 ACE_hthread_t hthread_list
[],
2312 ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list");
2313 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2315 size_t hthread_count
= 0;
2317 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2321 if (hthread_count
>= n
)
2326 if (iter
.next ()->grp_id_
== grp_id
)
2328 hthread_list
[hthread_count
] = iter
.next ()->thr_handle_
;
2333 return ACE_Utils::truncate_cast
<ssize_t
> (hthread_count
);
2337 ACE_Thread_Manager::set_grp (ACE_Task_Base
*task
, int grp_id
)
2339 ACE_TRACE ("ACE_Thread_Manager::set_grp");
2340 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2342 for (ACE_Double_Linked_List_Iterator
<ACE_Thread_Descriptor
> iter (this->thr_list_
);
2346 if (iter
.next ()->task_
== task
)
2348 iter
.next ()->grp_id_
= grp_id
;
2356 ACE_Thread_Manager::get_grp (ACE_Task_Base
*task
, int &grp_id
)
2358 ACE_TRACE ("ACE_Thread_Manager::get_grp");
2359 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex
, ace_mon
, this->lock_
, -1));
2361 ACE_FIND (this->find_task (task
), ptr
);
2362 grp_id
= ptr
->grp_id_
;
2366 ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Descriptor_Base
);
2368 ACE_END_VERSIONED_NAMESPACE_DECL