mxw_wotlk_azerothcore/deps/acelite/ace/Task.cpp

283 lines
7.3 KiB
C++

#include "ace/Task.h"
#include "ace/Module.h"
#if !defined (__ACE_INLINE__)
#include "ace/Task.inl"
#endif /* __ACE_INLINE__ */
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_Task_Base::ACE_Task_Base (ACE_Thread_Manager *thr_man)
: thr_count_ (0),
thr_mgr_ (thr_man),
flags_ (0),
grp_id_ (-1)
,last_thread_id_ (0)
{
}
ACE_Task_Base::~ACE_Task_Base (void)
{
}
/// Default ACE_Task service routine
int
ACE_Task_Base::svc (void)
{
ACE_TRACE ("ACE_Task_Base::svc");
return 0;
}
/// Default ACE_Task open routine
int
ACE_Task_Base::open (void *)
{
ACE_TRACE ("ACE_Task_Base::open");
return 0;
}
/// Default ACE_Task close routine
int
ACE_Task_Base::close (u_long)
{
ACE_TRACE ("ACE_Task_Base::close");
return 0;
}
/// Forward the call to close() so that existing applications don't
/// break.
int
ACE_Task_Base::module_closed (void)
{
return this->close (1);
}
/// Default ACE_Task put routine.
int
ACE_Task_Base::put (ACE_Message_Block *, ACE_Time_Value *)
{
ACE_TRACE ("ACE_Task_Base::put");
return 0;
}
/// Wait for all threads running in a task to exit.
int
ACE_Task_Base::wait (void)
{
ACE_TRACE ("ACE_Task_Base::wait");
// If we don't have a thread manager, we probably were never
// activated.
if (this->thr_mgr () != 0)
return this->thr_mgr ()->wait_task (this);
else
return 0;
}
/// Suspend a task.
int
ACE_Task_Base::suspend (void)
{
ACE_TRACE ("ACE_Task_Base::suspend");
ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
if (this->thr_count_ > 0)
return this->thr_mgr_->suspend_task (this);
return 0;
}
/// Resume a suspended task.
int
ACE_Task_Base::resume (void)
{
ACE_TRACE ("ACE_Task_Base::resume");
ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
if (this->thr_count_ > 0)
return this->thr_mgr_->resume_task (this);
return 0;
}
int
ACE_Task_Base::activate (long flags,
int n_threads,
int force_active,
long priority,
int grp_id,
ACE_Task_Base *task,
ACE_hthread_t thread_handles[],
void *stack[],
size_t stack_size[],
ACE_thread_t thread_ids[],
const char* thr_name[])
{
ACE_TRACE ("ACE_Task_Base::activate");
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
// If the task passed in is zero, we will use <this>
if (task == 0)
task = this;
if (this->thr_count_ > 0 && force_active == 0)
return 1; // Already active.
else
{
if (this->thr_count_ > 0 && this->grp_id_ != -1)
// If we're joining an existing group of threads then make
// sure to use its group id.
grp_id = this->grp_id_;
this->thr_count_ += n_threads;
}
// Use the ACE_Thread_Manager singleton if we're running as an
// active object and the caller didn't supply us with a
// Thread_Manager.
if (this->thr_mgr_ == 0)
# if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
this->thr_mgr_ = ACE_THREAD_MANAGER_SINGLETON::instance ();
# else /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
this->thr_mgr_ = ACE_Thread_Manager::instance ();
# endif /* ACE_THREAD_MANAGER_LACKS_STATICS */
int grp_spawned = -1;
if (thread_ids == 0)
// Thread Ids were not specified
grp_spawned =
this->thr_mgr_->spawn_n (n_threads,
&ACE_Task_Base::svc_run,
(void *) this,
flags,
priority,
grp_id,
task,
thread_handles,
stack,
stack_size,
thr_name);
else
// thread names were specified
grp_spawned =
this->thr_mgr_->spawn_n (thread_ids,
n_threads,
&ACE_Task_Base::svc_run,
(void *) this,
flags,
priority,
grp_id,
stack,
stack_size,
thread_handles,
task,
thr_name);
if (grp_spawned == -1)
{
// If spawn_n fails, restore original thread count.
this->thr_count_ -= n_threads;
return -1;
}
if (this->grp_id_ == -1)
this->grp_id_ = grp_spawned;
#if defined(ACE_TANDEM_T1248_PTHREADS)
ACE_OS::memcpy( &this->last_thread_id_, '\0', sizeof(this->last_thread_id_));
#else
this->last_thread_id_ = 0; // Reset to prevent inadvertant match on ID
#endif /* defined (ACE_TANDEM_T1248_PTHREADS) */
return 0;
#else
{
// Keep the compiler from complaining.
ACE_UNUSED_ARG (flags);
ACE_UNUSED_ARG (n_threads);
ACE_UNUSED_ARG (force_active);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (grp_id);
ACE_UNUSED_ARG (task);
ACE_UNUSED_ARG (thread_handles);
ACE_UNUSED_ARG (stack);
ACE_UNUSED_ARG (stack_size);
ACE_UNUSED_ARG (thread_ids);
ACE_UNUSED_ARG (thr_name);
ACE_NOTSUP_RETURN (-1);
}
#endif /* ACE_MT_SAFE */
}
void
ACE_Task_Base::cleanup (void *object, void *)
{
ACE_Task_Base *t = (ACE_Task_Base *) object;
// The thread count must be decremented first in case the <close>
// hook does something crazy like "delete this".
{
ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, t->lock_));
t->thr_count_--;
if (0 == t->thr_count_)
t->last_thread_id_ = ACE_Thread::self ();
}
// @@ Is it possible to pass in the exit status somehow?
t->close ();
// t is undefined here. close() could have deleted it.
}
#if defined (ACE_HAS_SIG_C_FUNC)
extern "C" void
ACE_Task_Base_cleanup (void *object, void *)
{
ACE_Task_Base::cleanup (object, 0);
}
#endif /* ACE_HAS_SIG_C_FUNC */
ACE_THR_FUNC_RETURN
ACE_Task_Base::svc_run (void *args)
{
ACE_TRACE ("ACE_Task_Base::svc_run");
ACE_Task_Base *t = (ACE_Task_Base *) args;
// Register ourself with our <Thread_Manager>'s thread exit hook
// mechanism so that our close() hook will be sure to get invoked
// when this thread exits.
#if defined ACE_HAS_SIG_C_FUNC
t->thr_mgr ()->at_exit (t, ACE_Task_Base_cleanup, 0);
#else
t->thr_mgr ()->at_exit (t, ACE_Task_Base::cleanup, 0);
#endif /* ACE_HAS_SIG_C_FUNC */
// Call the Task's svc() hook method.
int const svc_status = t->svc ();
ACE_THR_FUNC_RETURN status;
#if defined (ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN)
// Reinterpret case between integral types is not mentioned in the C++ spec
status = static_cast<ACE_THR_FUNC_RETURN> (svc_status);
#else
status = reinterpret_cast<ACE_THR_FUNC_RETURN> (svc_status);
#endif /* ACE_HAS_INTEGRAL_TYPE_THR_FUNC_RETURN */
// If we changed this zero change the other if in OS.cpp Thread_Adapter::invoke
#if 1
// Call the <Task->close> hook.
ACE_Thread_Manager *thr_mgr_ptr = t->thr_mgr ();
// This calls the Task->close () hook.
t->cleanup (t, 0);
// This prevents a second invocation of the cleanup code
// (called later by <ACE_Thread_Manager::exit>.
thr_mgr_ptr->at_exit (t, 0, 0);
#endif
return status;
}
ACE_END_VERSIONED_NAMESPACE_DECL