diff options
Diffstat (limited to 'deps/acelite/ace/Thread_Manager.cpp')
-rw-r--r-- | deps/acelite/ace/Thread_Manager.cpp | 2379 |
1 files changed, 0 insertions, 2379 deletions
diff --git a/deps/acelite/ace/Thread_Manager.cpp b/deps/acelite/ace/Thread_Manager.cpp deleted file mode 100644 index 172e4a43af..0000000000 --- a/deps/acelite/ace/Thread_Manager.cpp +++ /dev/null @@ -1,2379 +0,0 @@ -#include "ace/TSS_T.h" -#include "ace/Thread_Manager.h" -#include "ace/Dynamic.h" -#include "ace/Object_Manager.h" -#include "ace/Singleton.h" -#include "ace/Auto_Ptr.h" -#include "ace/Guard_T.h" -#include "ace/Time_Value.h" -#include "ace/OS_NS_sys_time.h" -#include "ace/Truncate.h" - -#if !defined (__ACE_INLINE__) -#include "ace/Thread_Manager.inl" -#endif /* __ACE_INLINE__ */ - -ACE_BEGIN_VERSIONED_NAMESPACE_DECL - -ACE_At_Thread_Exit::~ACE_At_Thread_Exit (void) -{ - this->do_apply (); -} - -ACE_At_Thread_Exit_Func::~ACE_At_Thread_Exit_Func (void) -{ - this->do_apply (); -} - -ACE_ALLOC_HOOK_DEFINE(ACE_At_Thread_Exit_Func) - -void -ACE_At_Thread_Exit_Func::apply (void) -{ - this->func_ (this->object_, this->param_); -} - -ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Control) -ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Manager) - -#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) -// Process-wide Thread Manager. -ACE_Thread_Manager *ACE_Thread_Manager::thr_mgr_ = 0; - -// Controls whether the Thread_Manager is deleted when we shut down -// (we can only delete it safely if we created it!) -bool ACE_Thread_Manager::delete_thr_mgr_ = false; -#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ - -ACE_TSS_TYPE (ACE_Thread_Exit) *ACE_Thread_Manager::thr_exit_ = 0; - -int -ACE_Thread_Manager::set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr) -{ - if (ACE_Thread_Manager::thr_exit_ == 0) - ACE_Thread_Manager::thr_exit_ = ptr; - else - return -1; - return 0; -} - -void -ACE_Thread_Manager::dump (void) -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Thread_Manager::dump"); - // Cast away const-ness of this in order to use its non-const lock_. - ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, - ((ACE_Thread_Manager *) this)->lock_)); - - ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_)); - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncurrent_count_ = %d"), this->thr_list_.size ())); - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - iter.next ()->dump (); - } - - ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -#endif /* ACE_HAS_DUMP */ -} - -ACE_Thread_Descriptor::~ACE_Thread_Descriptor (void) -{ - delete this->sync_; -} - -void -ACE_Thread_Descriptor::at_pop (int apply) -{ - ACE_TRACE ("ACE_Thread_Descriptor::at_pop"); - // Get first at from at_exit_list - ACE_At_Thread_Exit* at = this->at_exit_list_; - // Remove at from at_exit list - this->at_exit_list_ = at->next_; - // Apply if required - if (apply) - { - at->apply (); - // Do the apply method - at->was_applied (true); - // Mark at has been applied to avoid double apply from - // at destructor - } - // If at is not owner delete at. - if (!at->is_owner ()) - delete at; -} - -void -ACE_Thread_Descriptor::at_push (ACE_At_Thread_Exit* cleanup, bool is_owner) -{ - ACE_TRACE ("ACE_Thread_Descriptor::at_push"); - cleanup->is_owner (is_owner); - cleanup->td_ = this; - cleanup->next_ = at_exit_list_; - at_exit_list_ = cleanup; -} - -int -ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit& cleanup) -{ - ACE_TRACE ("ACE_Thread_Descriptor::at_exit"); - at_push (&cleanup, 1); - return 0; -} - -int -ACE_Thread_Descriptor::at_exit (ACE_At_Thread_Exit* cleanup) -{ - ACE_TRACE ("ACE_Thread_Descriptor::at_exit"); - if (cleanup==0) - return -1; - else - { - this->at_push (cleanup); - return 0; - } -} - -void -ACE_Thread_Descriptor::do_at_exit () -{ - ACE_TRACE ("ACE_Thread_Descriptor::do_at_exit"); - while (at_exit_list_!=0) - this->at_pop (); -} - -void -ACE_Thread_Descriptor::terminate () -{ - ACE_TRACE ("ACE_Thread_Descriptor::terminate"); - - if (!terminated_) - { - ACE_Log_Msg* log_msg = this->log_msg_; - terminated_ = true; - // Run at_exit hooks - this->do_at_exit (); - // We must remove Thread_Descriptor from Thread_Manager list - if (this->tm_ != 0) - { - int close_handle = 0; - -#if !defined (ACE_HAS_VXTHREADS) - // Threads created with THR_DAEMON shouldn't exist here, but - // just to be safe, let's put it here. - - if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_JOINING)) - { - if (ACE_BIT_DISABLED (this->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (this->flags_, THR_JOINABLE)) - { - // Mark thread as terminated. - ACE_SET_BITS (this->thr_state_, ACE_Thread_Manager::ACE_THR_TERMINATED); - tm_->register_as_terminated (this); - // Must copy the information here because td will be - // "freed" below. - } -#if defined (ACE_WIN32) - else - { - close_handle = 1; - } -#endif /* ACE_WIN32 */ - } -#endif /* !ACE_HAS_VXTHREADS */ - - // Remove thread descriptor from the table. 'this' is invalid - // upon return. - if (this->tm_ != 0) - { - // remove_thr makes use of 'this' invalid on return. - // Code below will free log_msg, so clear our pointer - // now - it's already been saved in log_msg. - this->log_msg_ = 0; - tm_->remove_thr (this, close_handle); - } - } - - // Check if we need delete ACE_Log_Msg instance - // If ACE_TSS_cleanup was not executed first log_msg == 0 - if (log_msg == 0) - { - // Only inform to ACE_TSS_cleanup that it must delete the log instance - // setting ACE_LOG_MSG thr_desc to 0. - ACE_LOG_MSG->thr_desc (0); - } - else - { - delete log_msg; - } - } -} - -int -ACE_Thread_Descriptor::at_exit (void *object, - ACE_CLEANUP_FUNC cleanup_hook, - void *param) -{ - ACE_TRACE ("ACE_Thread_Descriptor::at_exit"); - // To keep compatibility, when cleanup_hook is null really is a at_pop - // without apply. - if (cleanup_hook == 0) - { - if (this->at_exit_list_!= 0) - this->at_pop(0); - } - else - { - ACE_At_Thread_Exit* cleanup = 0; - ACE_NEW_RETURN (cleanup, - ACE_At_Thread_Exit_Func (object, - cleanup_hook, - param), - -1); - this->at_push (cleanup); - } - return 0; -} - -void -ACE_Thread_Descriptor::dump (void) const -{ -#if defined (ACE_HAS_DUMP) - ACE_TRACE ("ACE_Thread_Descriptor::dump"); - ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_id_ = %d"), this->thr_id_)); - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_handle_ = %d"), this->thr_handle_)); - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ngrp_id_ = %d"), this->grp_id_)); - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_state_ = %d"), this->thr_state_)); - ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %x\n"), this->flags_)); - - ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -#endif /* ACE_HAS_DUMP */ -} - -ACE_Thread_Descriptor::ACE_Thread_Descriptor (void) - : log_msg_ (0), - at_exit_list_ (0), - tm_ (0), - terminated_ (false) -{ - ACE_TRACE ("ACE_Thread_Descriptor::ACE_Thread_Descriptor"); - ACE_NEW (this->sync_, - ACE_DEFAULT_THREAD_MANAGER_LOCK); -} - -void -ACE_Thread_Descriptor::acquire_release (void) -{ - // Just try to acquire the lock then release it. -#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN) - if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED)) -#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */ - { - this->sync_->acquire (); - // Acquire the lock before removing <td> from the thread table. If - // this thread is in the table already, it should simply acquire the - // lock easily. - - // Once we get the lock, we must have registered. - ACE_ASSERT (ACE_BIT_ENABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED)); - - this->sync_->release (); - // Release the lock before putting it back to freelist. - } -} - -void -ACE_Thread_Descriptor::acquire (void) -{ - // Just try to acquire the lock then release it. -#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN) - if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED)) -#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */ - { - this->sync_->acquire (); - } -} - -void -ACE_Thread_Descriptor::release (void) -{ - // Just try to acquire the lock then release it. -#if defined (ACE_THREAD_MANAGER_USES_SAFE_SPAWN) - if (ACE_BIT_DISABLED (this->thr_state_, ACE_Thread_Manager::ACE_THR_SPAWNED)) -#endif /* ACE_THREAD_MANAGER_USES_SAFE_SPAWN */ - { - this->sync_->release (); - // Release the lock before putting it back to freelist. - } -} - -// The following macro simplifies subsequence code. -#define ACE_FIND(OP,INDEX) \ - ACE_Thread_Descriptor *INDEX = OP; \ - -ACE_Thread_Descriptor * -ACE_Thread_Manager::thread_descriptor (ACE_thread_t thr_id) -{ - ACE_TRACE ("ACE_Thread_Manager::thread_descriptor"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); - - ACE_FIND (this->find_thread (thr_id), ptr); - return ptr; -} - -ACE_Thread_Descriptor * -ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle) -{ - ACE_TRACE ("ACE_Thread_Manager::hthread_descriptor"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); - - ACE_FIND (this->find_hthread (thr_handle), ptr); - return ptr; -} - -// Return the thread descriptor (indexed by ACE_hthread_t). - -int -ACE_Thread_Manager::thr_self (ACE_hthread_t &self) -{ - ACE_TRACE ("ACE_Thread_Manager::thr_self"); - - ACE_Thread_Descriptor *desc = - this->thread_desc_self (); - - if (desc == 0) - return -1; - else - desc->self (self); - - return 0; -} - -// Initialize the synchronization variables. - -ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc, - size_t lwm, - size_t inc, - size_t hwm) - : grp_id_ (1), - automatic_wait_ (1) -#if defined (ACE_HAS_THREADS) - , zero_cond_ (lock_) -#endif /* ACE_HAS_THREADS */ - , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL, - prealloc, lwm, hwm, inc) -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - , join_cond_ (this->lock_) -#endif -{ - ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager"); -} - -ACE_Thread_Manager::ACE_Thread_Manager (const ACE_Condition_Attributes &attributes, - size_t prealloc, - size_t lwm, - size_t inc, - size_t hwm) - : grp_id_ (1), - automatic_wait_ (1) -#if defined (ACE_HAS_THREADS) - , zero_cond_ (lock_, attributes) -#endif /* ACE_HAS_THREADS */ - , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL, - prealloc, lwm, hwm, inc) -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - , join_cond_ (this->lock_) -#endif -{ -#if !defined (ACE_HAS_THREADS) - ACE_UNUSED_ARG (attributes); -#endif /* ACE_HAS_THREADS */ - ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager"); -} - -#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) -ACE_Thread_Manager * -ACE_Thread_Manager::instance (void) -{ - ACE_TRACE ("ACE_Thread_Manager::instance"); - - if (ACE_Thread_Manager::thr_mgr_ == 0) - { - // Perform Double-Checked Locking Optimization. - ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, - *ACE_Static_Object_Lock::instance (), 0)); - - if (ACE_Thread_Manager::thr_mgr_ == 0) - { - ACE_NEW_RETURN (ACE_Thread_Manager::thr_mgr_, - ACE_Thread_Manager, - 0); - ACE_Thread_Manager::delete_thr_mgr_ = true; - } - } - - return ACE_Thread_Manager::thr_mgr_; -} - -ACE_Thread_Manager * -ACE_Thread_Manager::instance (ACE_Thread_Manager *tm) -{ - ACE_TRACE ("ACE_Thread_Manager::instance"); - ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, - *ACE_Static_Object_Lock::instance (), 0)); - - ACE_Thread_Manager *t = ACE_Thread_Manager::thr_mgr_; - // We can't safely delete it since we don't know who created it! - ACE_Thread_Manager::delete_thr_mgr_ = false; - - ACE_Thread_Manager::thr_mgr_ = tm; - return t; -} - -void -ACE_Thread_Manager::close_singleton (void) -{ - ACE_TRACE ("ACE_Thread_Manager::close_singleton"); - - ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, - *ACE_Static_Object_Lock::instance ())); - - if (ACE_Thread_Manager::delete_thr_mgr_) - { - // First, we clean up the thread descriptor list. - ACE_Thread_Manager::thr_mgr_->close (); - delete ACE_Thread_Manager::thr_mgr_; - ACE_Thread_Manager::thr_mgr_ = 0; - ACE_Thread_Manager::delete_thr_mgr_ = false; - } - - ACE_Thread_Exit::cleanup (ACE_Thread_Manager::thr_exit_); -} -#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */ - -// Close up and release all resources. - -int -ACE_Thread_Manager::close () -{ - ACE_TRACE ("ACE_Thread_Manager::close"); - - // Clean up the thread descriptor list. - if (this->automatic_wait_) - this->wait (0, 1); - else - { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - this->remove_thr_all (); - } - - return 0; -} - -ACE_Thread_Manager::~ACE_Thread_Manager (void) -{ - ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager"); - this->close (); -} - - -// Run the entry point for thread spawned under the control of the -// <ACE_Thread_Manager>. This must be an extern "C" to make certain -// compilers happy... -// -// The interaction with <ACE_Thread_Exit> and -// <ace_thread_manager_adapter> works like this, with -// ACE_HAS_THREAD_SPECIFIC_STORAGE or ACE_HAS_TSS_EMULATION: -// -// o Every thread in the <ACE_Thread_Manager> is run with -// <ace_thread_manager_adapter>. -// -// o <ace_thread_manager_adapter> retrieves the singleton -// <ACE_Thread_Exit> instance from <ACE_Thread_Exit::instance>. -// The singleton gets created in thread-specific storage -// in the first call to that function. The key point is that the -// instance is in thread-specific storage. -// -// o A thread can exit by various means, such as <ACE_Thread::exit>, C++ -// or Win32 exception, "falling off the end" of the thread entry -// point function, etc. -// -// o If you follow this so far, now it gets really fun . . . -// When the thread-specific storage (for the thread that -// is being destroyed) is cleaned up, the OS threads package (or -// the ACE emulation of thread-specific storage) will destroy any -// objects that are in thread-specific storage. It has a list of -// them, and just walks down the list and destroys each one. -// -// o That's where the ACE_Thread_Exit destructor gets called. - -#if defined(ACE_USE_THREAD_MANAGER_ADAPTER) -extern "C" void * -ace_thread_manager_adapter (void *args) -{ -#if defined (ACE_HAS_TSS_EMULATION) - // As early as we can in the execution of the new thread, allocate - // its local TS storage. Allocate it on the stack, to save dynamic - // allocation/dealloction. - void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]; - ACE_TSS_Emulation::tss_open (ts_storage); -#endif /* ACE_HAS_TSS_EMULATION */ - - ACE_Thread_Adapter *thread_args = reinterpret_cast<ACE_Thread_Adapter *> (args); - - // NOTE: this preprocessor directive should match the one in above - // ACE_Thread_Exit::instance (). With the Xavier Pthreads package, - // the exit_hook in TSS causes a seg fault. So, this works around - // that by creating exit_hook on the stack. -#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION) - // Obtain our thread-specific exit hook and make sure that it knows - // how to clean us up! Note that we never use this pointer directly - // (it's stored in thread-specific storage), so it's ok to - // dereference it here and only store it as a reference. - ACE_Thread_Exit &exit_hook = *ACE_Thread_Exit::instance (); -#else - // Without TSS, create an <ACE_Thread_Exit> instance. When this - // function returns, its destructor will be called because the - // object goes out of scope. The drawback with this appraoch is - // that the destructor _won't_ get called if <thr_exit> is called. - // So, threads shouldn't exit that way. Instead, they should return - // from <svc>. - ACE_Thread_Exit exit_hook; -#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */ - - // Keep track of the <Thread_Manager> that's associated with this - // <exit_hook>. - exit_hook.thr_mgr (thread_args->thr_mgr ()); - - // Invoke the user-supplied function with the args. - ACE_THR_FUNC_RETURN status = thread_args->invoke (); - - delete static_cast<ACE_Base_Thread_Adapter *> (thread_args); - - return reinterpret_cast<void *> (status); -} -#endif - -// Call the appropriate OS routine to spawn a thread. Should *not* be -// called with the lock_ held... - -int -ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func, - void *args, - long flags, - ACE_thread_t *t_id, - ACE_hthread_t *t_handle, - long priority, - int grp_id, - void *stack, - size_t stack_size, - ACE_Task_Base *task, - const char** thr_name) -{ - // First, threads created by Thread Manager should not be daemon threads. - // Using assertion is probably a bit too strong. However, it helps - // finding this kind of error as early as possible. Perhaps we can replace - // assertion by returning error. - ACE_ASSERT (ACE_BIT_DISABLED (flags, THR_DAEMON)); - - // Create a new thread running <func>. *Must* be called with the - // <lock_> held... - // Get a "new" Thread Descriptor from the freelist. -#if defined (ACE_HAS_CPP11) - std::unique_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ()); -#else - auto_ptr<ACE_Thread_Descriptor> new_thr_desc (this->thread_desc_freelist_.remove ()); -#endif /* ACE_HAS_CPP11 */ - - // Reset thread descriptor status - new_thr_desc->reset (this); - - ACE_Thread_Adapter *thread_args = 0; -# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) - ACE_NEW_RETURN (thread_args, - ACE_Thread_Adapter (func, - args, - (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME, - this, - new_thr_desc.get (), - ACE_OS_Object_Manager::seh_except_selector(), - ACE_OS_Object_Manager::seh_except_handler(), - flags), - -1); -# else - ACE_NEW_RETURN (thread_args, - ACE_Thread_Adapter (func, - args, - (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME, - this, - new_thr_desc.get (), - flags), - -1); -# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ -#if defined ACE_HAS_CPP11 - std::unique_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args)); -#else - auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args (static_cast<ACE_Base_Thread_Adapter *> (thread_args)); -#endif - - ACE_TRACE ("ACE_Thread_Manager::spawn_i"); - ACE_hthread_t thr_handle; - - ACE_thread_t thr_id; - if (t_id == 0) - t_id = &thr_id; - - // Acquire the <sync_> lock to block the spawned thread from - // removing this Thread Descriptor before it gets put into our - // thread table. - new_thr_desc->sync_->acquire (); - - int const result = ACE_Thread::spawn (func, - args, - flags, - t_id, - &thr_handle, - priority, - stack, - stack_size, - thread_args, - thr_name); - - if (result != 0) - { - // _Don't_ clobber errno here! result is either 0 or -1, and - // ACE_OS::thr_create () already set errno! D. Levine 28 Mar 1997 - // errno = result; - ACE_Errno_Guard guard (errno); // Lock release may smash errno - new_thr_desc->sync_->release (); - return -1; - } - auto_thread_args.release (); - -#if defined (ACE_HAS_WTHREADS) - // Have to duplicate handle if client asks for it. - // @@ How are thread handles implemented on AIX? Do they - // also need to be duplicated? - if (t_handle != 0) -# if defined (ACE_LACKS_DUPLICATEHANDLE) - *t_handle = thr_handle; -# else /* ! ACE_LACKS_DUP */ - (void) ::DuplicateHandle (::GetCurrentProcess (), - thr_handle, - ::GetCurrentProcess (), - t_handle, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); -# endif /* ! ACE_LACKS_DUP */ -#else /* ! ACE_HAS_WTHREADS */ - if (t_handle != 0) - *t_handle = thr_handle; -#endif /* ! ACE_HAS_WTHREADS */ - - // append_thr also put the <new_thr_desc> into Thread_Manager's - // double-linked list. Only after this point, can we manipulate - // double-linked list from a spawned thread's context. - return this->append_thr (*t_id, - thr_handle, - ACE_THR_SPAWNED, - grp_id, - task, - flags, - new_thr_desc.release ()); -} - -int -ACE_Thread_Manager::spawn (ACE_THR_FUNC func, - void *args, - long flags, - ACE_thread_t *t_id, - ACE_hthread_t *t_handle, - long priority, - int grp_id, - void *stack, - size_t stack_size, - const char** thr_name) -{ - ACE_TRACE ("ACE_Thread_Manager::spawn"); - - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - if (grp_id == -1) - grp_id = this->grp_id_++; // Increment the group id. - - if (priority != ACE_DEFAULT_THREAD_PRIORITY) - ACE_CLR_BITS (flags, THR_INHERIT_SCHED); - - if (this->spawn_i (func, - args, - flags, - t_id, - t_handle, - priority, - grp_id, - stack, - stack_size, - 0, - thr_name) == -1) - return -1; - - return grp_id; -} - -// Create N new threads running FUNC. - -int -ACE_Thread_Manager::spawn_n (size_t n, - ACE_THR_FUNC func, - void *args, - long flags, - long priority, - int grp_id, - ACE_Task_Base *task, - ACE_hthread_t thread_handles[], - void *stack[], - size_t stack_size[], - const char* thr_name[]) -{ - ACE_TRACE ("ACE_Thread_Manager::spawn_n"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - if (grp_id == -1) - grp_id = this->grp_id_++; // Increment the group id. - - for (size_t i = 0; i < n; i++) - { - // @@ What should happen if this fails?! e.g., should we try to - // cancel the other threads that we've already spawned or what? - if (this->spawn_i (func, - args, - flags, - 0, - thread_handles == 0 ? 0 : &thread_handles[i], - priority, - grp_id, - stack == 0 ? 0 : stack[i], - stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i], - task, - thr_name == 0 ? 0 : &thr_name [i]) == -1) - return -1; - } - - return grp_id; -} - -// Create N new threads running FUNC. - -int -ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[], - size_t n, - ACE_THR_FUNC func, - void *args, - long flags, - long priority, - int grp_id, - void *stack[], - size_t stack_size[], - ACE_hthread_t thread_handles[], - ACE_Task_Base *task, - const char* thr_name[]) -{ - ACE_TRACE ("ACE_Thread_Manager::spawn_n"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - if (grp_id == -1) - grp_id = this->grp_id_++; // Increment the group id. - - for (size_t i = 0; i < n; i++) - { - // @@ What should happen if this fails?! e.g., should we try to - // cancel the other threads that we've already spawned or what? - if (this->spawn_i (func, - args, - flags, - thread_ids == 0 ? 0 : &thread_ids[i], - thread_handles == 0 ? 0 : &thread_handles[i], - priority, - grp_id, - stack == 0 ? 0 : stack[i], - stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i], - task, - thr_name == 0 ? 0 : &thr_name [i]) == -1) - return -1; - } - - return grp_id; -} - -// Append a thread into the pool (does not check for duplicates). -// Must be called with locks held. - -int -ACE_Thread_Manager::append_thr (ACE_thread_t t_id, - ACE_hthread_t t_handle, - ACE_UINT32 thr_state, - int grp_id, - ACE_Task_Base *task, - long flags, - ACE_Thread_Descriptor *td) -{ - ACE_TRACE ("ACE_Thread_Manager::append_thr"); - ACE_Thread_Descriptor *thr_desc = 0; - - if (td == 0) - { - ACE_NEW_RETURN (thr_desc, - ACE_Thread_Descriptor, - -1); - thr_desc->tm_ = this; - // Setup the Thread_Manager. - } - else - thr_desc = td; - - thr_desc->thr_id_ = t_id; - thr_desc->thr_handle_ = t_handle; - thr_desc->grp_id_ = grp_id; - thr_desc->task_ = task; - thr_desc->flags_ = flags; - - this->thr_list_.insert_head (thr_desc); - ACE_SET_BITS (thr_desc->thr_state_, thr_state); - thr_desc->sync_->release (); - - return 0; -} - -// Return the thread descriptor (indexed by ACE_hthread_t). - -ACE_Thread_Descriptor * -ACE_Thread_Manager::find_hthread (ACE_hthread_t h_id) -{ - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (ACE_OS::thr_cmp (iter.next ()->thr_handle_, h_id)) - { - return iter.next (); - } - } - - return 0; -} - -// Locate the index in the table associated with <t_id>. Must be -// called with the lock held. - -ACE_Thread_Descriptor * -ACE_Thread_Manager::find_thread (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::find_thread"); - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (ACE_OS::thr_equal (iter.next ()->thr_id_, t_id)) - { - return iter.next (); - } - } - return 0; -} - -// Insert a thread into the pool (checks for duplicates and doesn't -// allow them to be inserted twice). - -int -ACE_Thread_Manager::insert_thr (ACE_thread_t t_id, - ACE_hthread_t t_handle, - int grp_id, - long flags) -{ - ACE_TRACE ("ACE_Thread_Manager::insert_thr"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - // Check for duplicates and bail out if we're already registered... - if (this->find_thread (t_id) != 0 ) - return -1; - - if (grp_id == -1) - grp_id = this->grp_id_++; - - if (this->append_thr (t_id, - t_handle, - ACE_THR_SPAWNED, - grp_id, - 0, - flags) == -1) - return -1; - - return grp_id; -} - -// Run the registered hooks when the thread exits. - -void -ACE_Thread_Manager::run_thread_exit_hooks (int i) -{ -#if 0 // currently unused! - ACE_TRACE ("ACE_Thread_Manager::run_thread_exit_hooks"); - - // @@ Currently, we have just one hook. This should clearly be - // generalized to support an arbitrary number of hooks. - - ACE_Thread_Descriptor *td = this->thread_desc_self (); - for (ACE_Cleanup_Info_Node *iter = td->cleanup_info_->pop_front (); - iter != 0; - iter = cleanup_info_->pop_front ()) - { - if (iter->cleanup_hook () != 0) - { - (*iter->cleanup_hook ()) (iter->object (), iter->param ()); - } - delete iter; - } - - ACE_UNUSED_ARG (i); -#else - ACE_UNUSED_ARG (i); -#endif /* 0 */ -} - -// Remove a thread from the pool. Must be called with locks held. - -void -ACE_Thread_Manager::remove_thr (ACE_Thread_Descriptor *td, - int close_handler) -{ - ACE_TRACE ("ACE_Thread_Manager::remove_thr"); - - td->tm_ = 0; - this->thr_list_.remove (td); - -#if defined (ACE_WIN32) - if (close_handler != 0) - ::CloseHandle (td->thr_handle_); -#else - ACE_UNUSED_ARG (close_handler); -#endif /* ACE_WIN32 */ - - this->thread_desc_freelist_.add (td); - -#if defined (ACE_HAS_THREADS) - // Tell all waiters when there are no more threads left in the pool. - if (this->thr_list_.size () == 0) - this->zero_cond_.broadcast (); -#endif /* ACE_HAS_THREADS */ -} - -// Repeatedly call remove_thr on all table entries until there -// is no thread left. Must be called with lock held. -void -ACE_Thread_Manager::remove_thr_all (void) -{ - ACE_Thread_Descriptor *td = 0; - - while ((td = this->thr_list_.delete_head ()) != 0) - { - this->remove_thr (td, 1); - } -} - -// ------------------------------------------------------------------ -// Factor out some common behavior to simplify the following methods. -#define ACE_THR_OP(OP,STATE) \ - int result = OP (td->thr_handle_); \ - if (result == -1) { \ - if (errno != ENOTSUP) \ - this->thr_to_be_removed_.enqueue_tail (td); \ - return -1; \ - } \ - else { \ - ACE_SET_BITS (td->thr_state_, STATE); \ - return 0; \ - } - -int -ACE_Thread_Manager::join_thr (ACE_Thread_Descriptor *td, int) -{ - ACE_TRACE ("ACE_Thread_Manager::join_thr"); - -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - if (ACE_BIT_DISABLED (td->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (td->flags_, THR_JOINABLE)) - { - if (td->terminated_) - return 0; - ACE_SET_BITS (td->thr_state_, ACE_THR_JOINING); - } - else - { - errno = EINVAL; - return -1; - } - - const ACE_thread_t waiting_id = td->thr_id_; - - while (true) - { - if (this->join_cond_.wait () == -1) - return -1; - - bool found = false; - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done () && !found; iter.advance ()) - if (ACE_OS::thr_equal (iter.next ()->thr_id_, waiting_id)) - found = true; - if (!found) - break; - } - -#else - int const result = ACE_Thread::join (td->thr_handle_); - if (result != 0) - { - // Since the thread are being joined, we should - // let it remove itself from the list. - - // this->remove_thr (td); - errno = result; - return -1; - } -#endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN - - return 0; -} - -int -ACE_Thread_Manager::suspend_thr (ACE_Thread_Descriptor *td, int) -{ - ACE_TRACE ("ACE_Thread_Manager::suspend_thr"); - - int const result = ACE_Thread::suspend (td->thr_handle_); - if (result == -1) { - if (errno != ENOTSUP) - this->thr_to_be_removed_.enqueue_tail (td); - return -1; - } - else { - ACE_SET_BITS (td->thr_state_, ACE_THR_SUSPENDED); - return 0; - } -} - -int -ACE_Thread_Manager::resume_thr (ACE_Thread_Descriptor *td, int) -{ - ACE_TRACE ("ACE_Thread_Manager::resume_thr"); - - int const result = ACE_Thread::resume (td->thr_handle_); - if (result == -1) { - if (errno != ENOTSUP) - this->thr_to_be_removed_.enqueue_tail (td); - return -1; - } - else { - ACE_CLR_BITS (td->thr_state_, ACE_THR_SUSPENDED); - return 0; - } -} - -int -ACE_Thread_Manager::cancel_thr (ACE_Thread_Descriptor *td, int async_cancel) -{ - ACE_TRACE ("ACE_Thread_Manager::cancel_thr"); - // Must set the state first and then try to cancel the thread. - ACE_SET_BITS (td->thr_state_, ACE_THR_CANCELLED); - - if (async_cancel != 0) - // Note that this call only does something relevant if the OS - // platform supports asynchronous thread cancellation. Otherwise, - // it's a no-op. - return ACE_Thread::cancel (td->thr_id_); - - return 0; -} - -int -ACE_Thread_Manager::kill_thr (ACE_Thread_Descriptor *td, int signum) -{ - ACE_TRACE ("ACE_Thread_Manager::kill_thr"); - - ACE_thread_t tid = td->thr_id_; - - int const result = ACE_Thread::kill (tid, signum); - - if (result != 0) - { - // Only remove a thread from us when there is a "real" error. - if (errno != ENOTSUP) - this->thr_to_be_removed_.enqueue_tail (td); - - return -1; - } - - return 0; -} - -// ------------------------------------------------------------------ -// Factor out some common behavior to simplify the following methods. -#define ACE_EXECUTE_OP(OP, ARG) \ - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); \ - ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); \ - ACE_FIND (this->find_thread (t_id), ptr); \ - if (ptr == 0) \ - { \ - errno = ENOENT; \ - return -1; \ - } \ - int const result = OP (ptr, ARG); \ - ACE_Errno_Guard error (errno); \ - while (! this->thr_to_be_removed_.is_empty ()) { \ - ACE_Thread_Descriptor * td = 0; \ - this->thr_to_be_removed_.dequeue_head (td); \ - this->remove_thr (td, 1); \ - } \ - return result - -// Suspend a single thread. - -int -ACE_Thread_Manager::suspend (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::suspend"); - ACE_EXECUTE_OP (this->suspend_thr, 0); -} - -// Resume a single thread. - -int -ACE_Thread_Manager::resume (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::resume"); - ACE_EXECUTE_OP (this->resume_thr, 0); -} - -// Cancel a single thread. - -int -ACE_Thread_Manager::cancel (ACE_thread_t t_id, int async_cancel) -{ - ACE_TRACE ("ACE_Thread_Manager::cancel"); - ACE_EXECUTE_OP (this->cancel_thr, async_cancel); -} - -// Send a signal to a single thread. - -int -ACE_Thread_Manager::kill (ACE_thread_t t_id, int signum) -{ - ACE_TRACE ("ACE_Thread_Manager::kill"); - ACE_EXECUTE_OP (this->kill_thr, signum); -} - -int -ACE_Thread_Manager::check_state (ACE_UINT32 state, - ACE_thread_t id, - int enable) -{ - ACE_TRACE ("ACE_Thread_Manager::check_state"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - ACE_UINT32 thr_state; - - int self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ()); - - // If we're checking the state of our thread, try to get the cached - // value out of TSS to avoid lookup. - if (self_check) - { - ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc (); - if (desc == 0) - return 0; // Always return false. - thr_state = desc->thr_state_; - } - else - { - // Not calling from self, have to look it up from the list. - ACE_FIND (this->find_thread (id), ptr); - if (ptr == 0) - return 0; - thr_state = ptr->thr_state_; - } - if (enable) - return ACE_BIT_ENABLED (thr_state, state); - - return ACE_BIT_DISABLED (thr_state, state); -} - -// Test if a single thread has terminated. - -int -ACE_Thread_Manager::testterminate (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::testterminate"); - return this->check_state (ACE_THR_TERMINATED, t_id); -} - -// Test if a single thread is suspended. - -int -ACE_Thread_Manager::testsuspend (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::testsuspend"); - return this->check_state (ACE_THR_SUSPENDED, t_id); -} - -// Test if a single thread is active (i.e., resumed). - -int -ACE_Thread_Manager::testresume (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::testresume"); - return this->check_state (ACE_THR_SUSPENDED, t_id, 0); -} - -// Test if a single thread is cancelled. - -int -ACE_Thread_Manager::testcancel (ACE_thread_t t_id) -{ - ACE_TRACE ("ACE_Thread_Manager::testcancel"); - return this->check_state (ACE_THR_CANCELLED, t_id); -} - -// Thread information query functions. - -int -ACE_Thread_Manager::hthread_within (ACE_hthread_t handle) -{ - ACE_TRACE ("ACE_Thread_Manager::hthread_within"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1)); - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (ACE_OS::thr_cmp(iter.next ()->thr_handle_, handle)) - { - return 1; - } - } - - return 0; -} - -int -ACE_Thread_Manager::thread_within (ACE_thread_t tid) -{ - ACE_TRACE ("ACE_Thread_Manager::thread_within"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1)); - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid)) - { - return 1; - } - } - - return 0; -} - -// Get group ids for a particular thread id. - -int -ACE_Thread_Manager::get_grp (ACE_thread_t t_id, int &grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::get_grp"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - ACE_FIND (this->find_thread (t_id), ptr); - - if (ptr) - grp_id = ptr->grp_id_; - else - return -1; - return 0; -} - -// Set group ids for a particular thread id. - -int -ACE_Thread_Manager::set_grp (ACE_thread_t t_id, int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::set_grp"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - ACE_FIND (this->find_thread (t_id), ptr); - if (ptr) - ptr->grp_id_ = grp_id; - else - return -1; - return 0; -} - -// Suspend a group of threads. - -int -ACE_Thread_Manager::apply_grp (int grp_id, - ACE_THR_MEMBER_FUNC func, - int arg) -{ - ACE_TRACE ("ACE_Thread_Manager::apply_grp"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_monx, this->lock_, -1)); - ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); - - int result = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (iter.next ()->grp_id_ == grp_id) - { - if ((this->*func) (iter.next (), arg) == -1) - { - result = -1; - } - } - } - - // Must remove threads after we have traversed the thr_list_ to - // prevent clobber thr_list_'s integrity. - - if (! this->thr_to_be_removed_.is_empty ()) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); - - for (ACE_Thread_Descriptor *td; - this->thr_to_be_removed_.dequeue_head (td) != -1; - ) - this->remove_thr (td, 1); - } - - return result; -} - -int -ACE_Thread_Manager::suspend_grp (int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::suspend_grp"); - return this->apply_grp (grp_id, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr)); -} - -// Resume a group of threads. - -int -ACE_Thread_Manager::resume_grp (int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::resume_grp"); - return this->apply_grp (grp_id, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr)); -} - -// Kill a group of threads. - -int -ACE_Thread_Manager::kill_grp (int grp_id, int signum) -{ - ACE_TRACE ("ACE_Thread_Manager::kill_grp"); - return this->apply_grp (grp_id, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr), signum); -} - -// Cancel a group of threads. - -int -ACE_Thread_Manager::cancel_grp (int grp_id, int async_cancel) -{ - ACE_TRACE ("ACE_Thread_Manager::cancel_grp"); - return this->apply_grp (grp_id, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr), - async_cancel); -} - -int -ACE_Thread_Manager::apply_all (ACE_THR_MEMBER_FUNC func, int arg) -{ - ACE_TRACE ("ACE_Thread_Manager::apply_all"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); - - int result = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if ((this->*func)(iter.next (), arg) == -1) - { - result = -1; - } - } - - // Must remove threads after we have traversed the thr_list_ to - // prevent clobber thr_list_'s integrity. - - if (! this->thr_to_be_removed_.is_empty ()) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); - - for (ACE_Thread_Descriptor *td; - this->thr_to_be_removed_.dequeue_head (td) != -1; - ) - this->remove_thr (td, 1); - } - - return result; -} - -// Resume all threads that are suspended. - -int -ACE_Thread_Manager::resume_all (void) -{ - ACE_TRACE ("ACE_Thread_Manager::resume_all"); - return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr)); -} - -int -ACE_Thread_Manager::suspend_all (void) -{ - ACE_TRACE ("ACE_Thread_Manager::suspend_all"); - return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr)); -} - -int -ACE_Thread_Manager::kill_all (int sig) -{ - ACE_TRACE ("ACE_Thread_Manager::kill_all"); - return this->apply_all (&ACE_Thread_Manager::kill_thr, sig); -} - -int -ACE_Thread_Manager::cancel_all (int async_cancel) -{ - ACE_TRACE ("ACE_Thread_Manager::cancel_all"); - return this->apply_all (ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr), - async_cancel); -} - -int -ACE_Thread_Manager::join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status) -{ - ACE_TRACE ("ACE_Thread_Manager::join"); - - bool found = false; - ACE_Thread_Descriptor_Base tdb; - - { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - -#if !defined (ACE_HAS_VXTHREADS) - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_); - !biter.done (); - biter.advance ()) - { - if (ACE_OS::thr_equal (biter.next ()->thr_id_, tid)) - { - ACE_Thread_Descriptor_Base *tdbl = biter.advance_and_remove (false); -#ifndef ACE_LACKS_PTHREAD_JOIN - if (ACE_Thread::join (tdbl->thr_handle_, status) == -1) - { - return -1; - } -#endif - delete tdbl; - - // return immediately if we've found the thread we want to join. - return 0; - } - } -#endif /* !ACE_HAS_VXTHREADS */ - - typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t; - for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ()) - { - // If threads are created as THR_DETACHED or THR_DAEMON, we - // can't help much. - if (ACE_OS::thr_equal (iter.next ()->thr_id_,tid) && - (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE))) - { - tdb = *iter.next (); - ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING); - found = true; - break; - } - } - - if (!found) - return -1; - // Didn't find the thread we want or the thread is not joinable. - -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - ACE_UNUSED_ARG (status); // not currently supported without pthread_join - - while (found) - { - if (this->join_cond_.wait () == -1) - return -1; - - found = false; - for (iter_t iter (this->thr_list_); !iter.done () && !found; iter.advance ()) - if (ACE_OS::thr_equal (iter.next ()->thr_id_, tid) && - (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE))) - found = true; - } - -#endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN - - } - -#ifndef ACE_LACKS_PTHREAD_JOIN - if (ACE_Thread::join (tdb.thr_handle_, status) == -1) - return -1; -#endif - - return 0; -} - -// Wait for group of threads - -int -ACE_Thread_Manager::wait_grp (int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::wait_grp"); - - int copy_count = 0; - ACE_Thread_Descriptor_Base *copy_table = 0; - - // We have to make sure that while we wait for these threads to - // exit, we do not have the lock. Therefore we make a copy of all - // interesting entries and let go of the lock. - { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - -#if !defined (ACE_HAS_VXTHREADS) - ACE_NEW_RETURN (copy_table, - ACE_Thread_Descriptor_Base [this->thr_list_.size () - + this->terminated_thr_list_.size ()], - -1); -#else - ACE_NEW_RETURN (copy_table, - ACE_Thread_Descriptor_Base [this->thr_list_.size ()], - -1); -#endif /* !ACE_HAS_VXTHREADS */ - - typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t; - for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ()) - { - // If threads are created as THR_DETACHED or THR_DAEMON, we - // can't help much. - if (iter.next ()->grp_id_ == grp_id && - (ACE_BIT_DISABLED (iter.next ()->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE))) - { - ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING); - copy_table[copy_count++] = *iter.next (); - } - } - -#if !defined (ACE_HAS_VXTHREADS) - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> biter (this->terminated_thr_list_); - !biter.done (); - biter.advance ()) - { - // If threads are created as THR_DETACHED or THR_DAEMON, we - // can't help much. - if (biter.next ()->grp_id_ == grp_id) - { - ACE_Thread_Descriptor_Base *tdb = biter.advance_and_remove (false); - copy_table[copy_count++] = *tdb; - delete tdb; - } - } -#endif /* !ACE_HAS_VXTHREADS */ - -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - - while (copy_count) - { - if (this->join_cond_.wait () == -1) - { - delete[] copy_table; - return -1; - } - - copy_count = 0; - for (iter_t iter (this->thr_list_); !iter.done () && !copy_count; iter.advance ()) - if (iter.next ()->grp_id_ == grp_id && - ACE_BIT_ENABLED (iter.next ()->thr_state_, ACE_THR_JOINING) && - (ACE_BIT_DISABLED (iter.next ()->flags_, - THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE))) - ++copy_count; - } - -#endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN - } - - // Now actually join() with all the threads in this group. - int result = 0; - - for (int i = 0; - i < copy_count && result != -1; - i++) - { - if (ACE_Thread::join (copy_table[i].thr_handle_) == -1) - result = -1; - } - - delete [] copy_table; - - return result; -} - -// Must be called when thread goes out of scope to clean up its table -// slot. - -ACE_THR_FUNC_RETURN -ACE_Thread_Manager::exit (ACE_THR_FUNC_RETURN status, bool do_thread_exit) -{ - ACE_TRACE ("ACE_Thread_Manager::exit"); -#if defined (ACE_WIN32) - // Remove detached thread handle. - - if (do_thread_exit) - { -#if 0 - // @@ This callback is now taken care of by TSS_Cleanup. Do we - // need it anymore? - - // On Win32, if we really wants to exit from a thread, we must - // first clean up the thread specific storage. By doing so, - // ACE_Thread_Manager::exit will be called again with - // do_thr_exit = 0 and cleaning up the ACE_Cleanup_Info (but not - // exiting the thread.) After the following call returns, we - // are safe to exit this thread. - delete ACE_Thread_Exit::instance (); -#endif /* 0 */ - ACE_Thread::exit (status); - } -#endif /* ACE_WIN32 */ - - // Just hold onto the guard while finding this thread's id and - { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); - - // Find the thread id, but don't use the cache. It might have been - // deleted already. - ACE_thread_t const id = ACE_OS::thr_self (); - ACE_Thread_Descriptor* td = this->find_thread (id); - if (td != 0) - { - // @@ We call Thread_Descriptor terminate this realize the cleanup - // process itself. - td->terminate(); - -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - this->join_cond_.broadcast (); -#endif - } - } - - if (do_thread_exit) - { - ACE_Thread::exit (status); - // On reasonable systems <ACE_Thread::exit> should not return. - // However, due to horrible semantics with Win32 thread-specific - // storage this call can return (don't ask...). - } - - return 0; -} - -// Wait for all the threads to exit. - -int -ACE_Thread_Manager::wait (const ACE_Time_Value *timeout, - bool abandon_detached_threads, - bool use_absolute_time) -{ - ACE_TRACE ("ACE_Thread_Manager::wait"); - - ACE_Auto_Ptr<ACE_Time_Value> local_timeout; - // Check to see if we're using absolute time or not. - if (use_absolute_time == false && timeout != 0) - { - // create time value duplicate (preserves time policy) - local_timeout.reset (timeout->duplicate ()); - // convert time value to absolute time - (*local_timeout) = local_timeout->to_absolute_time (); - // replace original time by abs time duplicate - timeout = local_timeout.get (); - } - -#if !defined (ACE_HAS_VXTHREADS) - ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> term_thr_list_copy; -#endif /* ACE_HAS_VXTHREADS */ - -#if defined (ACE_HAS_THREADS) - { - // Just hold onto the guard while waiting. - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - if (ACE_Object_Manager::shutting_down () != 1) - { - // Program is not shutting down. Perform a normal wait on threads. - if (abandon_detached_threads != 0) - { - ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> - iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (ACE_BIT_ENABLED (iter.next ()->flags_, - THR_DETACHED | THR_DAEMON) - && ACE_BIT_DISABLED (iter.next ()->flags_, THR_JOINABLE)) - { - this->thr_to_be_removed_.enqueue_tail (iter.next ()); - ACE_SET_BITS (iter.next ()->thr_state_, ACE_THR_JOINING); - } - } - - if (! this->thr_to_be_removed_.is_empty ()) - { - ACE_Thread_Descriptor *td = 0; - while (this->thr_to_be_removed_.dequeue_head (td) != -1) - this->remove_thr (td, 1); - } - } - - while (this->thr_list_.size () > 0) - if (this->zero_cond_.wait (timeout) == -1) - return -1; - } - else - // Program is shutting down, no chance to wait on threads. - // Therefore, we'll just remove threads from the list. - this->remove_thr_all (); - -#if !defined (ACE_HAS_VXTHREADS) - ACE_Thread_Descriptor_Base* item = 0; - while ((item = this->terminated_thr_list_.delete_head ()) != 0) - { - term_thr_list_copy.insert_tail (item); - } -#endif /* ACE_HAS_VXTHREADS */ - // Release the guard, giving other threads a chance to run. - } - -#if !defined (ACE_HAS_VXTHREADS) - // @@ VxWorks doesn't support thr_join (yet.) We are working - // on our implementation. Chorus'es thr_join seems broken. - ACE_Thread_Descriptor_Base *item = 0; - - while ((item = term_thr_list_copy.delete_head ()) != 0) - { -#ifndef ACE_LACKS_PTHREAD_JOIN - if (ACE_BIT_DISABLED (item->flags_, THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (item->flags_, THR_JOINABLE)) - // Detached handles shouldn't reached here. - (void) ACE_Thread::join (item->thr_handle_); -#endif - delete item; - } - -#endif /* !ACE_HAS_VXTHREADS */ -#else - ACE_UNUSED_ARG (timeout); - ACE_UNUSED_ARG (abandon_detached_threads); -#endif /* ACE_HAS_THREADS */ - - return 0; -} - -int -ACE_Thread_Manager::apply_task (ACE_Task_Base *task, - ACE_THR_MEMBER_FUNC func, - int arg) -{ - ACE_TRACE ("ACE_Thread_Manager::apply_task"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - ACE_ASSERT (this->thr_to_be_removed_.is_empty ()); - - int result = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - if (iter.next ()->task_ == task - && (this->*func) (iter.next (), arg) == -1) - result = -1; - - // Must remove threads after we have traversed the thr_list_ to - // prevent clobber thr_list_'s integrity. - - if (! this->thr_to_be_removed_.is_empty ()) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); - - for (ACE_Thread_Descriptor *td = 0; - this->thr_to_be_removed_.dequeue_head (td) != -1; - ) - this->remove_thr (td, 1); - } - - return result; -} - -// Wait for all threads to exit a task. - -int -ACE_Thread_Manager::wait_task (ACE_Task_Base *task) -{ - int copy_count = 0; - ACE_Thread_Descriptor_Base *copy_table = 0; - - // We have to make sure that while we wait for these threads to - // exit, we do not have the lock. Therefore we make a copy of all - // interesting entries and let go of the lock. - { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - -#if !defined (ACE_HAS_VXTHREADS) - ACE_NEW_RETURN (copy_table, - ACE_Thread_Descriptor_Base [this->thr_list_.size () - + this->terminated_thr_list_.size ()], - -1); -#else - ACE_NEW_RETURN (copy_table, - ACE_Thread_Descriptor_Base [this->thr_list_.size ()], - -1); -#endif /* !ACE_HAS_VXTHREADS */ - - typedef ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter_t; - for (iter_t iter (this->thr_list_); !iter.done (); iter.advance ()) - { - // If threads are created as THR_DETACHED or THR_DAEMON, we - // can't wait on them here. - if (iter.next ()->task_ == task && - (ACE_BIT_DISABLED (iter.next ()->flags_, - THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, - THR_JOINABLE))) - { -# ifdef ACE_LACKS_PTHREAD_JOIN - if (ACE_OS::thr_equal (iter.next ()->thr_id_, ACE_OS::thr_self ())) - { - errno = EDEADLK; - delete[] copy_table; - return -1; - } -# endif - ACE_SET_BITS (iter.next ()->thr_state_, - ACE_THR_JOINING); - copy_table[copy_count++] = *iter.next (); - } - } - -#if !defined (ACE_HAS_VXTHREADS) - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor_Base> titer (this->terminated_thr_list_); - !titer.done (); - titer.advance ()) - { - // If threads are created as THR_DETACHED or THR_DAEMON, we can't help much here. - if (titer.next ()->task_ == task) - { - ACE_Thread_Descriptor_Base *tdb = titer.advance_and_remove (false); -# ifndef ACE_LACKS_PTHREAD_JOIN - copy_table[copy_count++] = *tdb; -# endif - delete tdb; - } - } -#endif /* !ACE_HAS_VXTHREADS */ - -#if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_PTHREAD_JOIN) - - while (copy_count) - { - if (this->join_cond_.wait () == -1) - { - delete[] copy_table; - return -1; - } - - copy_count = 0; - for (iter_t iter (this->thr_list_); !iter.done () && !copy_count; iter.advance ()) - if (iter.next ()->task_ == task && - ACE_BIT_ENABLED (iter.next ()->thr_state_, ACE_THR_JOINING) && - (ACE_BIT_DISABLED (iter.next ()->flags_, - THR_DETACHED | THR_DAEMON) - || ACE_BIT_ENABLED (iter.next ()->flags_, THR_JOINABLE))) - ++copy_count; - } - -#endif // ACE_HAS_THREADS && ACE_LACKS_PTHREAD_JOIN - } - - // Now to do the actual work - int result = 0; - - for (int i = 0; - i < copy_count && result != -1; - i++) - { - if (ACE_Thread::join (copy_table[i].thr_handle_) == -1) - result = -1; - } - - delete [] copy_table; - - return result; -} - -// Suspend a task - -int -ACE_Thread_Manager::suspend_task (ACE_Task_Base *task) -{ - ACE_TRACE ("ACE_Thread_Manager::suspend_task"); - return this->apply_task (task, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::suspend_thr)); -} - -// Resume a task. -int -ACE_Thread_Manager::resume_task (ACE_Task_Base *task) -{ - ACE_TRACE ("ACE_Thread_Manager::resume_task"); - return this->apply_task (task, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::resume_thr)); -} - -// Kill a task. - -int -ACE_Thread_Manager::kill_task (ACE_Task_Base *task, int /* signum */) -{ - ACE_TRACE ("ACE_Thread_Manager::kill_task"); - return this->apply_task (task, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::kill_thr)); -} - -// Cancel a task. -int -ACE_Thread_Manager::cancel_task (ACE_Task_Base *task, - int async_cancel) -{ - ACE_TRACE ("ACE_Thread_Manager::cancel_task"); - return this->apply_task (task, - ACE_THR_MEMBER_FUNC (&ACE_Thread_Manager::cancel_thr), - async_cancel); -} - -// Locate the index in the table associated with <task> from the -// beginning of the table up to an index. Must be called with the -// lock held. - -ACE_Thread_Descriptor * -ACE_Thread_Manager::find_task (ACE_Task_Base *task, size_t slot) -{ - ACE_TRACE ("ACE_Thread_Manager::find_task"); - - size_t i = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (i >= slot) - break; - - if (task == iter.next ()->task_) - return iter.next (); - - ++i; - } - - return 0; -} - -// Returns the number of ACE_Task in a group. - -int -ACE_Thread_Manager::num_tasks_in_group (int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::num_tasks_in_group"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - int tasks_count = 0; - size_t i = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (iter.next ()->grp_id_ == grp_id - && this->find_task (iter.next ()->task_, i) == 0 - && iter.next ()->task_ != 0) - { - ++tasks_count; - } - - ++i; - } - return tasks_count; -} - -// Returns the number of threads in an ACE_Task. - -int -ACE_Thread_Manager::num_threads_in_task (ACE_Task_Base *task) -{ - ACE_TRACE ("ACE_Thread_Manager::num_threads_in_task"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - int threads_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (iter.next ()->task_ == task) - { - ++threads_count; - } - } - - return threads_count; -} - -// Returns in task_list a list of ACE_Tasks registered with ACE_Thread_Manager. - -ssize_t -ACE_Thread_Manager::task_all_list (ACE_Task_Base *task_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::task_all_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t task_list_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (task_list_count >= n) - { - break; - } - - ACE_Task_Base *task_p = iter.next ()->task_; - - if (0 != task_p) - { - // This thread has a task pointer; see if it's already in the - // list. Don't add duplicates. - size_t i = 0; - - for (; i < task_list_count; ++i) - { - if (task_list[i] == task_p) - { - break; - } - } - - if (i == task_list_count) // No match - add this one - { - task_list[task_list_count++] = task_p; - } - } - } - - return ACE_Utils::truncate_cast<ssize_t> (task_list_count); -} - -// Returns in thread_list a list of all thread ids - -ssize_t -ACE_Thread_Manager::thread_all_list (ACE_thread_t thread_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::thread_all_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t thread_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (thread_count >= n) - { - break; - } - - thread_list[thread_count] = iter.next ()->thr_id_; - ++thread_count; - } - - return ACE_Utils::truncate_cast<ssize_t> (thread_count); -} - - -int -ACE_Thread_Manager::thr_state (ACE_thread_t id, - ACE_UINT32& state) -{ - ACE_TRACE ("ACE_Thread_Manager::thr_state"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - int const self_check = ACE_OS::thr_equal (id, ACE_OS::thr_self ()); - - // If we're checking the state of our thread, try to get the cached - // value out of TSS to avoid lookup. - if (self_check) - { - ACE_Thread_Descriptor *desc = ACE_LOG_MSG->thr_desc (); - - if (desc == 0) - { - return 0; // Always return false. - } - - state = desc->thr_state_; - } - else - { - // Not calling from self, have to look it up from the list. - ACE_FIND (this->find_thread (id), ptr); - - if (ptr == 0) - { - return 0; - } - - state = ptr->thr_state_; - } - - return 1; -} - -// Returns in task_list a list of ACE_Tasks in a group. - -ssize_t -ACE_Thread_Manager::task_list (int grp_id, - ACE_Task_Base *task_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::task_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - ACE_Task_Base **task_list_iterator = task_list; - size_t task_list_count = 0; - size_t i = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (task_list_count >= n) - { - break; - } - - if (iter.next ()->grp_id_ == grp_id - && this->find_task (iter.next ()->task_, i) == 0) - { - task_list_iterator[task_list_count] = iter.next ()->task_; - ++task_list_count; - } - - ++i; - } - - return ACE_Utils::truncate_cast<ssize_t> (task_list_count); -} - -// Returns in thread_list a list of thread ids in an ACE_Task. - -ssize_t -ACE_Thread_Manager::thread_list (ACE_Task_Base *task, - ACE_thread_t thread_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::thread_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t thread_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (thread_count >= n) - { - break; - } - - if (iter.next ()->task_ == task) - { - thread_list[thread_count] = iter.next ()->thr_id_; - ++thread_count; - } - } - - return ACE_Utils::truncate_cast<ssize_t> (thread_count); -} - -// Returns in thread_list a list of thread handles in an ACE_Task. - -ssize_t -ACE_Thread_Manager::hthread_list (ACE_Task_Base *task, - ACE_hthread_t hthread_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::hthread_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t hthread_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (hthread_count >= n) - { - break; - } - - if (iter.next ()->task_ == task) - { - hthread_list[hthread_count] = iter.next ()->thr_handle_; - ++hthread_count; - } - } - - return ACE_Utils::truncate_cast<ssize_t> (hthread_count); -} - -ssize_t -ACE_Thread_Manager::thread_grp_list (int grp_id, - ACE_thread_t thread_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::thread_grp_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t thread_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (thread_count >= n) - { - break; - } - - if (iter.next ()->grp_id_ == grp_id) - { - thread_list[thread_count] = iter.next ()->thr_id_; - thread_count++; - } - } - - return ACE_Utils::truncate_cast<ssize_t> (thread_count); -} - -// Returns in thread_list a list of thread handles in an ACE_Task. - -ssize_t -ACE_Thread_Manager::hthread_grp_list (int grp_id, - ACE_hthread_t hthread_list[], - size_t n) -{ - ACE_TRACE ("ACE_Thread_Manager::hthread_grp_list"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - size_t hthread_count = 0; - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (hthread_count >= n) - { - break; - } - - if (iter.next ()->grp_id_ == grp_id) - { - hthread_list[hthread_count] = iter.next ()->thr_handle_; - hthread_count++; - } - } - - return ACE_Utils::truncate_cast<ssize_t> (hthread_count); -} - -int -ACE_Thread_Manager::set_grp (ACE_Task_Base *task, int grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::set_grp"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - for (ACE_Double_Linked_List_Iterator<ACE_Thread_Descriptor> iter (this->thr_list_); - !iter.done (); - iter.advance ()) - { - if (iter.next ()->task_ == task) - { - iter.next ()->grp_id_ = grp_id; - } - } - - return 0; -} - -int -ACE_Thread_Manager::get_grp (ACE_Task_Base *task, int &grp_id) -{ - ACE_TRACE ("ACE_Thread_Manager::get_grp"); - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); - - ACE_FIND (this->find_task (task), ptr); - grp_id = ptr->grp_id_; - return 0; -} - -ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Descriptor_Base); - -ACE_END_VERSIONED_NAMESPACE_DECL |