在一个ACE项目中使用线程是再常见不过了。然而ACE线程做到了很好的管理。使用了ACE_Thread_Manager封装了很多东西。
该类是将启动的线程放到了一个双向链表里进行管理的。
当我们想启动一个线程的时候,我们就可以这样的使用
启动线程:
void* func(void*);
ACE_Thread_Manager::instance()->spawn(ACE_THR_FUNC(func), 0, THR_NEW_LWP);
线程阻塞,等待子线程退出:
ACE_Thread_Manager::instance()->wait();
ACE_Thread_Manager使用了单例模式。
ACE_Thread_Manager代码展示
带参构造函数
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)
{
ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
}
单例模式函数:
其中他ACE_Thread_Manager::delete_thr_mgr_ 布尔变量,当实例化的时候,设置true。
#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_);
}
析构函数,清除对象:
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 ();
}
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);
}
}
线程启动函数:
简单介绍一下参数:
func:线程函数,不用多数
args:线程函数参数,
flags:线程的属性控制Flags to control attributes of the spawned threads.
* @sa ACE_OS::thr_create() for descriptions of the
* possible flags values and their interactions.
t_id:线程id
t_handle: Pointer to a location to receive the spawned thread's
* thread handle. If 0, the handle is not returned.
priority:线程的优先级
grp_id:组id
stack:线程栈 stack_size:栈大小
size_t n:启动几次线程
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;
}
下面是函数,更具其名字应该能知道线程管理的意义了:
ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status = 0,
bool do_thread_exit = true);
/**
* Block until there are no more threads running in this thread
* manager or @c timeout expires.
*
* @param timeout is treated as "absolute" time by default, but this
* can be changed to "relative" time by setting the @c
* use_absolute_time to false.
* @param abandon_detached_threads If true, @c wait() will first
* check thru its thread list for
* threads with THR_DETACHED or
* THR_DAEMON flags set and remove
* these threads. Notice that
* unlike other @c wait_*() methods,
* by default, @c wait() does wait on
* all thread spawned by this
* thread manager no matter the detached
* flags are set or not unless it is
* called with @c
* abandon_detached_threads flag set.
* @param use_absolute_time If true then treat @c timeout as
* absolute time, else relative time.
* @return 0 on success * and -1 on failure.
*
* @note If this function is called while the @c
* ACE_Object_Manager is shutting down (as a result of program
* rundown via @c ACE::fini()), it will not wait for any threads to
* complete. If you must wait for threads spawned by this thread
* manager to complete and you are in a ACE rundown situation (such
* as your object is being destroyed by the @c ACE_Object_Manager)
* you can use @c wait_grp() instead.
*/
int wait (const ACE_Time_Value *timeout = 0,
bool abandon_detached_threads = false,
bool use_absolute_time = true);
/// Join a thread specified by @a tid. Do not wait on a detached thread.
int join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status = 0);
/**
* Block until there are no more threads running in a group.
* Returns 0 on success and -1 on failure. Notice that wait_grp
* will not wait on detached threads.
*/
int wait_grp (int grp_id);
/**
* Return the "real" handle to the calling thread, caching it if
* necessary in TSS to speed up subsequent lookups. This is
* necessary since on some platforms (e.g., Windows) we can't get this
* handle via direct method calls. Notice that you should *not*
* close the handle passed back from this method. It is used
* internally by Thread Manager. On the other hand, you *have to*
* use this internal thread handle when working on Thread_Manager.
* Return -1 if fail.
*/
int thr_self (ACE_hthread_t &);
/**
* Return the unique ID of the calling thread.
* Same as calling ACE_Thread::self().
*/
ACE_thread_t thr_self (void);
/**
* Returns a pointer to the current ACE_Task_Base we're executing
* in if this thread is indeed running in an ACE_Task_Base, else
* return 0.
*/
ACE_Task_Base *task (void);
/**
* @name Suspend and resume methods
*
* Suspend/resume is not supported on all platforms. For example, Pthreads
* does not support these functions.
*/
//@{
/// Suspend all threads
int suspend_all (void);
/// Suspend a single thread.
int suspend (ACE_thread_t);
/// Suspend a group of threads.
int suspend_grp (int grp_id);
/**
* True if @a t_id is inactive (i.e., suspended), else false. Always
* return false if @a t_id is not managed by the Thread_Manager.
*/
int testsuspend (ACE_thread_t t_id);
/// Resume all stopped threads
int resume_all (void);
/// Resume a single thread.
int resume (ACE_thread_t);
/// Resume a group of threads.
int resume_grp (int grp_id);
/**
* True if @a t_id is active (i.e., resumed), else false. Always
* return false if @a t_id is not managed by the Thread_Manager.
*/
int testresume (ACE_thread_t t_id);
//@}
// = Send signals to one or more threads without blocking.
/**
* Send @a signum to all stopped threads. Not supported on platforms
* that do not have advanced signal support, such as Win32.
*/
int kill_all (int signum);
/**
* Send the @a signum to a single thread. Not supported on platforms
* that do not have advanced signal support, such as Win32.
*/
int kill (ACE_thread_t, int signum);
/**
* Send @a signum to a group of threads, not supported on platforms
* that do not have advanced signal support, such as Win32.
*/
int kill_grp (int grp_id, int signum);
// = Cancel methods, which provides a cooperative thread-termination mechanism (will not block).
/**
* Cancel's all the threads.
*/
int cancel_all (int async_cancel = 0);
/**
* Cancel a single thread.
*/
int cancel (ACE_thread_t, int async_cancel = 0);
/**
* Cancel a group of threads.
*/
int cancel_grp (int grp_id, int async_cancel = 0);
/**
* True if @a t_id is cancelled, else false. Always return false if
* @a t_id is not managed by the Thread_Manager.
*/
int testcancel (ACE_thread_t t_id);
/**
* True if @a t_id has terminated (i.e., is no longer running),
* but the slot in the thread manager hasn't been reclaimed yet,
* else false. Always return false if @a t_id is not managed by the
* Thread_Manager.
*/
int testterminate (ACE_thread_t t_id);
/// Set group ids for a particular thread id.
int set_grp (ACE_thread_t,
int grp_id);
/// Get group ids for a particular thread id.
int get_grp (ACE_thread_t,
int &grp_id);
/**
* @name Task-related operations
*/
//@{
/**
* Block until there are no more threads running in a specified task.
* This method will not wait for either detached or daemon threads;
* the threads must have been spawned with the @c THR_JOINABLE flag.
* Upon successful completion, the threads have been joined, so further
* attempts to join with any of the waited-for threads will fail.
*
* @param task The ACE_Task_Base object whose threads are to waited for.
*
* @retval 0 Success.
* @retval -1 Failure (consult errno for further information).
*/
int wait_task (ACE_Task_Base *task);
/**
* Suspend all threads in an ACE_Task.
*/
int suspend_task (ACE_Task_Base *task);
/**
* Resume all threads in an ACE_Task.
*/
int resume_task (ACE_Task_Base *task);
/**
* Send a signal @a signum to all threads in an ACE_Task.
*/
int kill_task (ACE_Task_Base *task, int signum);
/**
* Cancel all threads in an ACE_Task. If is non-0,
* then asynchronously cancel these threads if the OS platform
* supports cancellation. Otherwise, perform a "cooperative"
* cancellation.
*/
int cancel_task (ACE_Task_Base *task, int async_cancel = 0);
//@}
// = Collect thread handles in the thread manager. Notice that
// the collected information is just a snapshot.
/// Check if the thread is managed by the thread manager. Return true if
/// the thread is found, false otherwise.
int hthread_within (ACE_hthread_t handle);
int thread_within (ACE_thread_t tid);
/// Returns the number of ACE_Task_Base in a group.
int num_tasks_in_group (int grp_id);
/// Returns the number of threads in an ACE_Task_Base.
int num_threads_in_task (ACE_Task_Base *task);
/**
* Returns a list of ACE_Task_Base pointers corresponding to the tasks
* that have active threads in a specified thread group.
*
* @param grp_id The thread group ID to obtain task pointers for.
*
* @param task_list is a pointer to an array to receive the list of pointers.
* The caller is responsible for supplying an array with at
* least @arg n entries.
*
* @param n The maximum number of ACE_Task_Base pointers to write
* in @arg task_list.
*
* @retval If successful, the number of pointers returned, which will be
* no greater than @arg n. Returns -1 on error.
*
* @note This method has no way to indicate if there are more than
* @arg n ACE_Task_Base pointers available. Therefore, it may be
* wise to guess a larger value of @arg n than one thinks in cases
* where the exact number of tasks is not known.
*
* @sa num_tasks_in_group(), task_all_list()
*/
ssize_t task_list (int grp_id,
ACE_Task_Base *task_list[],
size_t n);
/**
* Returns in @a thread_list a list of up to @a n thread ids in an
* ACE_Task_Base. The caller must allocate the memory for
* @a thread_list. In case of an error, -1 is returned. If no
* requested values are found, 0 is returned, otherwise correct
* number of retrieved values are returned.
*/
ssize_t thread_list (ACE_Task_Base *task,
ACE_thread_t thread_list[],
size_t n);
/**
* Returns in @a hthread_list a list of up to @a n thread handles in
* an ACE_Task_Base. The caller must allocate memory for
* @a hthread_list. In case of an error, -1 is returned. If no
* requested values are found, 0 is returned, otherwise correct
* number of retrieved values are returned.
*/
ssize_t hthread_list (ACE_Task_Base *task,
ACE_hthread_t hthread_list[],
size_t n);
/**
* Returns in @a thread_list a list of up to @a n thread ids in a
* group @a grp_id. The caller must allocate the memory for
* @a thread_list. In case of an error, -1 is returned. If no
* requested values are found, 0 is returned, otherwise correct
* number of retrieved values are returned.
*/
ssize_t thread_grp_list (int grp_id,
ACE_thread_t thread_list[],
size_t n);
/**
* Returns in @a hthread_list a list of up to @a n thread handles in
* a group @a grp_id. The caller must allocate memory for
* @a hthread_list.
*/
ssize_t hthread_grp_list (int grp_id,
ACE_hthread_t hthread_list[],
size_t n);
/**
* Returns a list of ACE_Task_Base pointers corresponding to the tasks
* that have active threads managed by this instance.
*
* @param task_list is a pointer to an array to receive the list of pointers.
* The caller is responsible for supplying an array with at
* least @arg n entries.
*
* @param n The maximum number of ACE_Task_Base pointers to write
* in @arg task_list.
*
* @retval If successful, the number of pointers returned, which will be
* no greater than @arg n. Returns -1 on error.
*
* @note This method has no way to indicate if there are more than
* @arg n ACE_Task_Base pointers available. Therefore, it may be
* wise to guess a larger value of @arg n than one thinks in cases
* where the exact number of tasks is not known.
*
* @sa count_threads()
*/
ssize_t task_all_list (ACE_Task_Base *task_list[],
size_t n);
/**
* Returns in @a thread_list a list of up to @a n thread ids. The
* caller must allocate the memory for @a thread_list. In case of an
* error, -1 is returned. If no requested values are found, 0 is
* returned, otherwise correct number of retrieved values are
* returned.
*/
ssize_t thread_all_list (ACE_thread_t thread_list[],
size_t n);
/// Set group ids for a particular task.
int set_grp (ACE_Task_Base *task, int grp_id);
/// Get group ids for a particular task.
int get_grp (ACE_Task_Base *task, int &grp_id);
/// Return a count of the current number of threads active in the
/// .
size_t count_threads (void) const;
/// Get the state of the thread. Returns false if the thread is not
/// managed by this thread manager.
int thr_state (ACE_thread_t id, ACE_UINT32& state);
/**
* Register an At_Thread_Exit hook and the ownership is acquire by
* Thread_Descriptor, this is the usual case when the AT is dynamically
* allocated.
*/
int at_exit (ACE_At_Thread_Exit* cleanup);
/// Register an At_Thread_Exit hook and the ownership is retained for the
/// caller. Normally used when the at_exit hook is created in stack.
int at_exit (ACE_At_Thread_Exit& cleanup);
/**
*
*****
* @deprecated This function is deprecated. Please use the previous two
* at_exit method. Notice that you should avoid mixing this method
* with the previous two at_exit methods.
*****
*
* Register an object (or array) for cleanup at
* thread termination. "cleanup_hook" points to a (global, or
* static member) function that is called for the object or array
* when it to be destroyed. It may perform any necessary cleanup
* specific for that object or its class. "param" is passed as the
* second parameter to the "cleanup_hook" function; the first
* parameter is the object (or array) to be destroyed.
* "cleanup_hook", for example, may delete the object (or array).
* If == 0, the
注意:必须在退出functor所属的线程的上下文中,向线程管理器登记这个退出functor.使用ACE_Thread_Manager::at_exit()方法登记退出functor;
ACE_Thread_Manager::wait()会等待所有的子线程退出,而不管与那些线程相关联的是哪个任务,当你有不止一个任务正在执行的时候,使用这个特性将会很方便;
注意:我们要把ACE_Thread_Manager类的实例当作一个单体对象使用;其原因是:在默认情况下,ACE会通过这个单体对象来管理所有的线程;尽管在大多数情况下,你会发现默认行为已经足够,你可以创建并使用多个线程管理器对象;
线程的取消:
取消是一种你可以用以消灭(zap)正在运行线程的途径.任何线程退出处理器都不会被调用,线程专有存储空间也不会被释放.你的线程将消失.在某些情况下,取消也是一种"必要的邪恶":为了退出一个长时间运行的、只进行计算的线程,或是终止一个阻塞在阻塞式调用上的线程.在大多数情况下,应用终止时取消线程是有意义的;
取消有以下几种模式:
A、延迟取消:
这种模式下,所有的取消操作都会被延迟到该线程的下一个取消点.取消点是代码中明确定义的点,在这个点上,线程或是已经阻塞,或是用ACE_Thread_Manager::testcancal()方法编写了显式的取消点.这种模式是用ACE构建的应用的默认模式;
B、协作式取消:
这种模式下,线程并没有被真正的取消,而是会在派生它们的ACE_Thread_Manager实例中被标记已取消.你可以调用ACE_Thread_Manager::testcalcel()方法来确定线程是否处在已取消状态.如果这样,你可以选择退出线程.这种模式避免了常规取消所带来的大多数讨厌的副作用.如果你想构建可移植的应用,就最好坚持使用这种取消模式;
C、异步取消:
这种模式下,取消操作可以在任意时刻被处理;运行在这种模式下的线程可能会难以管理.你可以把任何线程的取消状态从启用改为禁用,以确保线程不会在执行关键代码时被取消.你还可以使用线程清理处理器,它们将在线程取消时被调用,以确保线程的各不变项在取消过程中得以维持.
D、禁用取消:
调用ACE_Thread::disablecancel(),可以完全禁止取消某个线程;
ACE_Thread_Manager::cancel_task()方法可以用来取消一个线程;
下面的方法可以把线程的取消模式设置为异步取消模式:
cancel_state new_state;
new_state.cancelstate = PTHREAD_CANCEL_ENABLE;
new_state.canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
ACE_Thread::setcancelstate(new_state, 0);
更多文章,欢迎访问:http://blog.csdn.net/wallwind