#include <ace/Thread_Manager.h>
class ACE_Thread_Manager {
public:
friend class ACE_Thread_Control;
friend class ACE_Thread_Descriptor;
typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)( ACE_Thread_Descriptor *, int );
enum{ ACE_THR_IDLE = 0x00000000, ACE_THR_SPAWNED = 0x00000001, ACE_THR_RUNNING = 0x00000002, ACE_THR_SUSPENDED = 0x00000004, ACE_THR_CANCELLED = 0x00000008, ACE_THR_TERMINATED = 0x00000010, ACE_THR_JOINING = 0x10000000 };ACE_Thread_Manager ( size_t preaolloc = 0, size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM, size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC, size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM );
virtual ~ACE_Thread_Manager (void);
static ACE_Thread_Manager *instance (void);
static ACE_Thread_Manager *instance (ACE_Thread_Manager *);
static void close_singleton (void);
int open (size_t size = 0);
int close (void);
int spawn ( ACE_THR_FUNC func, void *args = 0, long flags = THR_NEW_LWP | THR_JOINABLE, ACE_thread_t * = 0, ACE_hthread_t *t_handle = 0, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack = 0, size_t stack_size = 0 );
int spawn_n ( size_t n, ACE_THR_FUNC func, void *args = 0, long flags = THR_NEW_LWP | THR_JOINABLE, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, ACE_Task_Base *task = 0, ACE_hthread_t thread_handles[] = 0, void *stack[] = 0, size_t stack_size[] = 0 );
int spawn_n ( ACE_thread_t thread_ids[], size_t n, ACE_THR_FUNC func, void *args, long flags, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack[] = 0, size_t stack_size[] = 0, ACE_hthread_t thread_handles[] = 0 );
void *exit (void *status = 0, int do_thread_exit = 1);
int wait ( const ACE_Time_Value *timeout = 0, int abandon_detached_threads = 0 );
int join (ACE_thread_t tid, void **status = 0);
int wait_grp (int grp_id);
ACE_Thread_Descriptor *thread_desc_self (void);
ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);
ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);
int thr_self (ACE_hthread_t &);
ACE_thread_t thr_self (void);
ACE_Task_Base *task (void);
int suspend_all (void);
int suspend (ACE_thread_t);
int suspend_grp (int grp_id);
int testsuspend (ACE_thread_t t_id);
int resume_all (void);
int resume (ACE_thread_t);
int resume_grp (int grp_id);
int testresume (ACE_thread_t t_id);
int kill_all (int signum);
int kill (ACE_thread_t, int signum);
int kill_grp (int grp_id, int signum);
int cancel_all (int async_cancel = 0);
int cancel (ACE_thread_t, int async_cancel = 0);
int cancel_grp (int grp_id, int async_cancel = 0);
int testcancel (ACE_thread_t t_id);
int set_grp (ACE_thread_t, int grp_id);
int get_grp (ACE_thread_t, int &grp_id);
int wait_task (ACE_Task_Base *task);
int suspend_task (ACE_Task_Base *task);
int resume_task (ACE_Task_Base *task);
int kill_task (ACE_Task_Base *task, int signum);
int cancel_task (ACE_Task_Base *task, int async_cancel = 0);
int hthread_within (ACE_hthread_t handle);
int thread_within (ACE_thread_t tid);
int num_tasks_in_group (int grp_id);
int num_threads_in_task (ACE_Task_Base *task);
int task_list (int grp_id, ACE_Task_Base *task_list[], size_t n);
int thread_list ( ACE_Task_Base *task, ACE_thread_t thread_list[], size_t n );
int hthread_list ( ACE_Task_Base *task, ACE_hthread_t hthread_list[], size_t n );
int thread_grp_list ( int grp_id, ACE_thread_t thread_list[], size_t n );
int hthread_grp_list ( int grp_id, ACE_hthread_t hthread_list[], size_t n );
int task_all_list (ACE_Task_Base *task_list[], size_t n);
int thread_all_list (ACE_thread_t thread_list[], size_t n);
int set_grp (ACE_Task_Base *task, int grp_id);
int get_grp (ACE_Task_Base *task, int &grp_id);
int count_threads (void) const;
int at_exit (ACE_At_Thread_Exit* cleanup);
int at_exit (ACE_At_Thread_Exit& cleanup);
int at_exit ( void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param );
void wait_on_exit (int dowait);
int wait_on_exit (void);
void dump (void);
ACE_ALLOC_HOOK_DECLARE;
protected:
virtual int spawn_i ( ACE_THR_FUNC func, void *args, long flags, ACE_thread_t * = 0, ACE_hthread_t *t_handle = 0, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack = 0, size_t stack_size = 0, ACE_Task_Base *task = 0 );
void run_thread_exit_hooks (int i);
ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id);
ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id);
ACE_Thread_Descriptor *find_task ( ACE_Task_Base *task, int slot = -1 );
int insert_thr ( ACE_thread_t t_id, ACE_hthread_t, int grp_id = -1, long flags = 0 );
int append_thr ( ACE_thread_t t_id, ACE_hthread_t, ACE_UINT32, int grp_id, ACE_Task_Base *task = 0, long flags = 0, ACE_Thread_Descriptor *td = 0 );
void remove_thr (ACE_Thread_Descriptor *td, int close_handler);
void remove_thr_all (void);
int check_state ( ACE_UINT32 state, ACE_thread_t thread, int enable = 1 );
int apply_task ( ACE_Task_Base *task, ACE_THR_MEMBER_FUNC, int = 0 );
int apply_grp (int grp_id, ACE_THR_MEMBER_FUNC func, int arg = 0);
int apply_all (ACE_THR_MEMBER_FUNC, int = 0);
int join_thr (ACE_Thread_Descriptor *td, int = 0);
int resume_thr (ACE_Thread_Descriptor *td, int = 0);
int suspend_thr (ACE_Thread_Descriptor *td, int = 0);
int kill_thr (ACE_Thread_Descriptor *td, int signum);
int cancel_thr (ACE_Thread_Descriptor *td, int async_cancel = 0);
int register_as_terminated (ACE_Thread_Descriptor *td);
ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;
ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;
int grp_id_;
int automatic_wait_;
ACE_Thread_Mutex lock_;
ACE_Condition_Thread_Mutex zero_cond_;
private:
ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_;static ACE_Thread_Manager *thr_mgr_;
static int delete_thr_mgr_;
};
Notice that if there're threads live beyond the scope of
main
, you are sure to have resource leaks in your program.
Remember to wait on threads before exiting main
if that
could happen in your programs.
ACE_Thread_Manager (
size_t preaolloc = 0,
size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM,
size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC,
size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM
);
virtual ~ACE_Thread_Manager (void);
static ACE_Thread_Manager *instance (void);
ACE_Thread_Manager
.
static ACE_Thread_Manager *instance (ACE_Thread_Manager *);
ACE_Thread_Manager
and return
existing pointer.
static void close_singleton (void);
int open (size_t size = 0);
int close (void);
close_singleton
, most global resources
are destroyed and thus, we don't try to wait but just clean up the thread
descriptor list.
The ACE_thread_t
* argument to each of the spawn
family member
functions is interpreted and used as shown in the following
table. NOTE: the final option, to provide task names, is _only_
supported on VxWorks!
Value of ACE_thread_t * argument Use Platforms ================================ ========================== ========= 0 Not used. All non-0 (and points to 0 char * The task name is passed All on VxWorks) back in the char *. non-0, points to non-0 char * The char * is used as VxWorks only the task name. The argument is not modified.
int spawn (
ACE_THR_FUNC func,
void *args = 0,
long flags = THR_NEW_LWP | THR_JOINABLE,
ACE_thread_t * = 0,
ACE_hthread_t *t_handle = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
void *stack = 0,
size_t stack_size = 0
);
func
.
Returns: on success a unique group id that can be used to control
other threads added to the same group. On failure, returns -1.
int spawn_n (
size_t n,
ACE_THR_FUNC func,
void *args = 0,
long flags = THR_NEW_LWP | THR_JOINABLE,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
ACE_Task_Base *task = 0,
ACE_hthread_t thread_handles[] = 0,
void *stack[] = 0,
size_t stack_size[] = 0
);
func
.
Returns: on success a unique group id that can be used to control
all of the threads in the same group. On failure, returns -1.
int spawn_n (
ACE_thread_t thread_ids[],
size_t n,
ACE_THR_FUNC func,
void *args,
long flags,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
void *stack[] = 0,
size_t stack_size[] = 0,
ACE_hthread_t thread_handles[] = 0
);
func
with argument arg
.
If thread_ids
!= 0 the thread_ids of successfully spawned
threads will be placed into the thread_ids
buffer (which must
be the same size as n
). If stack
!= 0 it is assumed to be an
array of n
pointers to the base of the stacks to use for the
threads being spawned. If stack_size
!= 0 it is assumed to be
an array of n
values indicating how big each of the
corresponding stack
s are. If thread_handles
!= 0 it is
assumed to be an array of n
thread_handles that will be
assigned the values of the thread handles being spawned. Returns
-1 on failure (errno
will explain...), otherwise returns the
group id of the threads.
void *exit (void *status = 0, int do_thread_exit = 1);
do_thread_exit
is
non-0 then ACE_Thread::exit
is called to exit the thread, in
which case status
is passed as the exit value of the thread.
Should _not_ be called by main thread.
int wait (
const ACE_Time_Value *timeout = 0,
int abandon_detached_threads = 0
);
Thread_Manager
or timeout
expires. Note that timeout
is
treated as "absolute" time. Returns 0 on success and -1 on
failure. If abandon_detached_threads
is set, 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 wait_* function, by default, 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
abandon_detached_threads
flag set.
NOTE that if this function is called while the ACE_Object_Manager
is shutting down (as a result of program rundown via 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
ACE_Object_Manager) you can use wait_grp instead.
int join (ACE_thread_t tid, void **status = 0);
tid
. Do not wait on a detached thread.
int wait_grp (int grp_id);
ACE_Thread_Descriptor *thread_desc_self (void);
ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);
ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);
int thr_self (ACE_hthread_t &);
ACE_thread_t thr_self (void);
ACE_Thread::self
). However, we put it here to be complete.
ACE_Task_Base *task (void);
ACE_Task_Base
we're executing
in if this thread is indeed running in an ACE_Task_Base
, else
return 0.
int suspend_all (void);
int suspend (ACE_thread_t);
int suspend_grp (int grp_id);
int testsuspend (ACE_thread_t t_id);
t_id
is inactive (i.e., suspended), else false.
int resume_all (void);
int resume (ACE_thread_t);
int resume_grp (int grp_id);
int testresume (ACE_thread_t t_id);
t_id
is active (i.e., resumed), else false.
int kill_all (int signum);
int kill (ACE_thread_t, int signum);
int kill_grp (int grp_id, int signum);
int cancel_all (int async_cancel = 0);
int cancel (ACE_thread_t, int async_cancel = 0);
int cancel_grp (int grp_id, int async_cancel = 0);
int testcancel (ACE_thread_t t_id);
t_id
is cancelled, else false.
int set_grp (ACE_thread_t, int grp_id);
int get_grp (ACE_thread_t, int &grp_id);
ACE_Thread Manager
. For example, the apply_task
method resembles the apply_thr
method, and suspend_task
resembles suspend_thr
.
int wait_task (ACE_Task_Base *task);
task
. Returns
0 on success and -1 on failure. Note that wait_task
will not
wait on detached threads.
int suspend_task (ACE_Task_Base *task);
int resume_task (ACE_Task_Base *task);
int kill_task (ACE_Task_Base *task, int signum);
signum
to all threads in an ACE_Task
.
int cancel_task (ACE_Task_Base *task, int async_cancel = 0);
ACE_Task
. If async_cancel
is non-0,
then asynchronously cancel these threads if the OS platform
supports cancellation. Otherwise, perform a "cooperative"
cancellation.
int hthread_within (ACE_hthread_t handle);
int thread_within (ACE_thread_t tid);
int num_tasks_in_group (int grp_id);
ACE_Task_Base
in a group.
int num_threads_in_task (ACE_Task_Base *task);
ACE_Task_Base
.
int task_list (int grp_id, ACE_Task_Base *task_list[], size_t n);
task_list
a list of up to n
ACE_Tasks
in a
group. The caller must allocate the memory for task_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.
int thread_list (
ACE_Task_Base *task,
ACE_thread_t thread_list[],
size_t n
);
thread_list
a list of up to n
thread ids in an
ACE_Task_Base
. The caller must allocate the memory for
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.
int hthread_list (
ACE_Task_Base *task,
ACE_hthread_t hthread_list[],
size_t n
);
hthread_list
a list of up to n
thread handles in
an ACE_Task_Base
. The caller must allocate memory for
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.
int thread_grp_list (
int grp_id,
ACE_thread_t thread_list[],
size_t n
);
thread_list
a list of up to n
thread ids in a
group grp_id
. The caller must allocate the memory for
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.
int hthread_grp_list (
int grp_id,
ACE_hthread_t hthread_list[],
size_t n
);
hthread_list
a list of up to n
thread handles in
a group grp_id
. The caller must allocate memory for
hthread_list
.
int task_all_list (ACE_Task_Base *task_list[], size_t n);
task_list
a list of up to n
ACE_Tasks
. The
caller must allocate the memory for task_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.
int thread_all_list (ACE_thread_t thread_list[], size_t n);
thread_list
a list of up to n
thread ids. The
caller must allocate the memory for 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.
int set_grp (ACE_Task_Base *task, int grp_id);
int get_grp (ACE_Task_Base *task, int &grp_id);
int count_threads (void) const;
Thread_Manager
.
int at_exit (ACE_At_Thread_Exit* cleanup);
int at_exit (ACE_At_Thread_Exit& cleanup);
int at_exit (
void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param
);
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 cleanup_hook
== 0, the object
will _NOT_ get cleanup at
thread exit. You can use this to cancel the previously added
at_exit.
void wait_on_exit (int dowait);
int wait_on_exit (void);
void dump (void);
ACE_ALLOC_HOOK_DECLARE;
int check_state (
ACE_UINT32 state,
ACE_thread_t thread,
int enable = 1
);
thread
is in a particular state
.
This call updates the TSS cache if possible to speed up
subsequent searches.
int apply_task (ACE_Task_Base *task, ACE_THR_MEMBER_FUNC, int = 0);
func
to all members of the table that match the task
int apply_grp (int grp_id, ACE_THR_MEMBER_FUNC func, int arg = 0);
func
to all members of the table that match the grp_id
.
int apply_all (ACE_THR_MEMBER_FUNC, int = 0);
func
to all members of the table.
int join_thr (ACE_Thread_Descriptor *td, int = 0);
tda
.
int resume_thr (ACE_Thread_Descriptor *td, int = 0);
tda
.
int suspend_thr (ACE_Thread_Descriptor *td, int = 0);
tda
.
int kill_thr (ACE_Thread_Descriptor *td, int signum);
signum
to the thread described in tda
.
int cancel_thr (ACE_Thread_Descriptor *td, int async_cancel = 0);
tda
.
int register_as_terminated (ACE_Thread_Descriptor *td);
terminated_thr_list_
.
ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;
ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;
ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;
int grp_id_;
int automatic_wait_;
ACE_Thread_Mutex lock_;
zero_cond_
.
ACE_Condition_Thread_Mutex zero_cond_;