1 // The following test was written by Hamutal Yanay & Ari Erev's
2 // (Ari_Erev@comverse.com).
4 // This test program test enhancements to the thread_manager and task
5 // classes. The purpose of these enhancements was to allow the
6 // thread_manager to recognize the concept of an ACE_Task and to be
7 // able to group ACE_Tasks in groups.
9 // There are two main ACE_Tasks in this sample:
11 // Invoker_Task - is run from main (). It's purpose is to run a number of
12 // ACE_Tasks of type Worker_Task. The number can be specified
13 // on the command line.
14 // After starting the tasks, the Invoker_Task groups all the tasks
15 // in one group and then uses the
16 // num_tasks_in_group () to find out if the real number of tasks
17 // that are now running (should be the same as the number of tasks
19 // It also, suspends and resumes all the threads in the group to
20 // test the suspend_grp () and resume_grp () methods.
21 // Then it waits for all the tasks to end.
23 // Worker_Task - ACE_Tasks that are started by the Invoker_Task.
24 // Each Worker_Task can start a number of threads.
25 // The Worker_Task threads perform some work (iteration). The number
26 // of the iterations can be specified on the command line.
28 // The command line syntax is:
30 // test_task [num_tasks] [num_threads] [num_iterations]
32 #include "ace/OS_NS_unistd.h"
33 #include "ace/OS_main.h"
35 #include "ace/Service_Config.h"
37 #if defined (ACE_HAS_THREADS)
41 class Invoker_Task
: public ACE_Task
<ACE_MT_SYNCH
>
44 Invoker_Task (ACE_Thread_Manager
*thr_mgr
,
49 // creats <n_tasks> and wait for them to finish
53 // Number of tasks to start.
55 // Number of threads per task.
57 // Number of iterations per thread.
60 class Worker_Task
: public ACE_Task
<ACE_MT_SYNCH
>
63 Worker_Task (ACE_Thread_Manager
*thr_mgr
,
68 //FUZZ: disable check_for_lack_ACE_OS
69 // Does a small work...
70 virtual int open (void * = NULL
);
71 //FUZZ: enable check_for_lack_ACE_OS
74 static size_t workers_count_
;
79 //FUZZ: disable check_for_lack_ACE_OS
80 // = Not needed for this test.
81 virtual int close (u_long
);
82 //FUZZ: enable check_for_lack_ACE_OS
84 virtual int put (ACE_Message_Block
*, ACE_Time_Value
*) { return 0; }
87 size_t Worker_Task::workers_count_
= 1;
90 Worker_Task::close (u_long
)
93 "(%t) closing task %d\n",
99 Worker_Task::Worker_Task (ACE_Thread_Manager
*thr_mgr
,
102 : ACE_Task
<ACE_MT_SYNCH
> (thr_mgr
),
103 index_ (Worker_Task::workers_count_
++),
104 n_threads_ (n_threads
),
105 n_iterations_ (n_iterations
)
110 Worker_Task::open (void *)
112 // Create the pool of worker threads.
113 return this->activate (THR_NEW_LWP
,
114 ACE_Utils::truncate_cast
<int> (this->n_threads_
),
124 ACE_DEBUG ((LM_DEBUG
,
125 " (%t) in worker %d\n",
128 for (size_t iterations
= 1;
129 iterations
<= this->n_iterations_
;
132 ACE_DEBUG ((LM_DEBUG
,
133 " (%t) in iteration %d\n",
138 ACE_DEBUG ((LM_DEBUG
,
139 " (%t) worker %d ends\n",
145 Invoker_Task::Invoker_Task (ACE_Thread_Manager
*thr_mgr
,
149 : ACE_Task
<ACE_MT_SYNCH
> (thr_mgr
),
151 n_threads_ (n_threads
),
152 n_iterations_ (n_iterations
)
154 // Create a single worker thread.
155 if (this->activate (THR_NEW_LWP
,
161 ACE_ERROR ((LM_ERROR
,
166 // Iterate <n_iterations> time printing off a message and "waiting"
167 // for all other threads to complete this iteration.
172 // Note that the ACE_Task::svc_run () method automatically adds us
173 // to the Thread_Manager when the thread begins.
175 ACE_Thread_Manager
*thr_mgr
=
176 ACE_Thread_Manager::instance ();
177 Worker_Task
**worker_task
= 0;
179 ACE_NEW_RETURN (worker_task
,
180 Worker_Task
*[n_tasks_
],
185 task
< this->n_tasks_
;
188 ACE_DEBUG ((LM_DEBUG
,
189 " (%t) in task %d\n",
192 ACE_NEW_RETURN (worker_task
[task
],
193 Worker_Task (thr_mgr
,
198 if (worker_task
[task
]->open () == -1)
199 ACE_ERROR_RETURN ((LM_ERROR
,
205 // Set all tasks to be one group
206 ACE_DEBUG ((LM_DEBUG
,
207 " (%t) setting tasks group id\n"));
210 task
< this->n_tasks_
;
212 if (thr_mgr
->set_grp (worker_task
[task
],
214 ACE_ERROR ((LM_DEBUG
,
219 thr_mgr
->num_tasks_in_group (1);
220 ACE_DEBUG ((LM_DEBUG
,
221 "Number of tasks in group 1: %d\n",
224 // Wait for 1 second and then suspend every thread in the group.
226 ACE_DEBUG ((LM_DEBUG
,
227 " (%t) suspending group\n"));
229 if (thr_mgr
->suspend_grp (1) == -1)
230 ACE_ERROR ((LM_DEBUG
,
234 // Wait for 3 more second and then resume every thread in the group.
235 ACE_OS::sleep (ACE_Time_Value (2));
237 ACE_DEBUG ((LM_DEBUG
,
238 " (%t) resuming group\n"));
240 if (thr_mgr
->resume_grp (1) == -1)
241 ACE_ERROR ((LM_DEBUG
,
245 // Wait for all the tasks to reach their exit point.
248 // Note that the ACE_Task::svc_run () method automatically removes
249 // us from the Thread_Manager when the thread exits.
253 // Default number of tasks and iterations.
254 static const size_t DEFAULT_TASKS
= 4;
255 static const size_t DEFAULT_ITERATIONS
= 5;
258 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
260 size_t n_tasks
= argc
> 1 ? ACE_OS::atoi (argv
[1]) : DEFAULT_TASKS
;
261 size_t n_threads
= argc
> 2 ? ACE_OS::atoi (argv
[2]) : ACE_DEFAULT_THREADS
;
262 size_t n_iterations
= argc
> 3 ? ACE_OS::atoi (argv
[3]) : DEFAULT_ITERATIONS
;
264 // Since ACE_Thread_Manager can only wait for all threads, we'll
265 // have special manager for the Invoker_Task.
266 ACE_Thread_Manager invoker_manager
;
268 Invoker_Task
invoker (&invoker_manager
,
273 // Wait for 1 second and then suspend the invoker task
275 ACE_DEBUG ((LM_DEBUG
,
276 " (%t) suspending invoker task\n"));
278 if (invoker_manager
.suspend_task (&invoker
) == -1)
279 ACE_ERROR ((LM_DEBUG
,
283 // Wait for 3 more second and then resume the invoker task.
284 ACE_OS::sleep (ACE_Time_Value (3));
286 ACE_DEBUG ((LM_DEBUG
,
287 " (%t) resuming invoker task\n"));
289 if (invoker_manager
.resume_task (&invoker
) == -1)
290 ACE_ERROR ((LM_DEBUG
,
294 // Wait for all the threads to reach their exit point.
295 invoker_manager
.wait ();
297 ACE_DEBUG ((LM_DEBUG
,
303 ACE_TMAIN (int, ACE_TCHAR
*[])
305 ACE_ERROR ((LM_ERROR
,
306 "threads not supported on this platform\n"));
309 #endif /* ACE_HAS_THREADS */