1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
// $Id$
// Exercise more tests for the ACE Tasks. This test can spawn off
// zillions of tasks and then wait for them using both polling and the
// ACE Thread Manager.
#include "ace/Task.h"
#include "ace/Service_Config.h"
#include "ace/Synch.h"
ACE_RCSID(Threads, task_two, "$Id$")
#if defined (ACE_HAS_THREADS)
typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
static int zero = 0;
static ATOMIC_INT task_count (zero);
static ATOMIC_INT max_count (zero);
static ATOMIC_INT wait_count (zero);
static int n_threads = 0;
// Default number of tasks.
static const int default_threads = ACE_DEFAULT_THREADS;
// Default number of times to run the test.
static const int default_iterations = 1000;
class Task_Test : public ACE_Task<ACE_MT_SYNCH>
{
public:
virtual int open (void *args = 0);
virtual int close (u_long flags = 0);
virtual int svc (void);
private:
static ACE_Thread_Mutex lock_;
};
ACE_Thread_Mutex Task_Test::lock_;
int
Task_Test::open (void *)
{
ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Task_Test::lock_, -1);
task_count++;
ACE_DEBUG ((LM_DEBUG, "(%t) creating Task_Test, task count = %d\n",
task_count.value ()));
return this->activate (THR_BOUND);
}
int
Task_Test::close (u_long)
{
ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Task_Test::lock_, -1);
task_count--;
ACE_DEBUG ((LM_DEBUG, "(%t) destroying Task_Test, task count = %d\n",
task_count.value ()));
wait_count--;
return 0;
}
int
Task_Test::svc (void)
{
wait_count++;
max_count++;
ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting\n"));
for (;;)
if (max_count >= n_threads)
break;
else
ACE_Thread::yield ();
ACE_DEBUG ((LM_DEBUG, "(%t) svc: finished waiting\n"));
return 0;
}
int
main (int argc, char *argv[])
{
n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : default_threads;
int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : default_iterations;
Task_Test **task_array = new Task_Test *[n_threads];
for (int i = 1; i <= n_iterations; i++)
{
ACE_DEBUG ((LM_DEBUG, "(%t) iteration = %d, max_count %d\n",
i, max_count.value ()));
max_count = 0;
ACE_DEBUG ((LM_DEBUG, "(%t) starting %d task%s\n",
n_threads, n_threads == 1 ? "" : "s"));
// Launch the new tasks.
for (int j = 0; j < n_threads; j++)
{
task_array[j] = new Task_Test;
// Activate the task, i.e., make it an active object.
task_array[j]->open ();
}
// Wait for initialization to kick in.
while (max_count == 0)
ACE_Thread::yield ();
ACE_DEBUG ((LM_DEBUG, "(%t) waiting for threads to finish\n"));
// Wait for the threads to finish this iteration.
while (max_count != n_threads && wait_count != 0)
ACE_Thread::yield ();
ACE_DEBUG ((LM_DEBUG,
"(%t) iteration %d finished, max_count %d, wait_count %d, waiting for tasks to exit\n",
i, max_count.value (), wait_count.value ()));
// Wait for all the tasks to exit.
ACE_Thread_Manager::instance ()->wait ();
// Delete the existing tasks.
for (int k = 0; k < n_threads; k++)
delete task_array[k];
}
delete [] task_array;
ACE_DEBUG ((LM_DEBUG, "(%t) shutting down the test\n"));
return 0;
}
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Atomic_Op<ACE_Thread_Mutex, int>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Atomic_Op<ACE_Thread_Mutex, int>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
#else
int
main (int, char *[])
{
ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
return 0;
}
#endif /* ACE_HAS_THREADS */
|