summaryrefslogtreecommitdiff
path: root/ACE/tests/Task_Group_Test.cpp
blob: 93017948af870058fcad2b757981369c377c726b (plain)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

//=============================================================================
/**
 *  @file    Task_Group_Test.cpp
 *
 *    This test program illustrates the logic of the grp_id handling
 *    mechanism in <ACE_Task_Base> and the <ACE_Thread_Manager>.
 *    Partially reuses test submitted by Paxton Mason in Bugzilla #2366
 *
 *  @author Martin Corino <mcorino@remedy.nl>
 */
//=============================================================================


#include "test_config.h"
#include "ace/Atomic_Op.h"
#include "ace/Task.h"
#include "ace/OS_NS_unistd.h"

#if defined (ACE_HAS_THREADS)

const int MAX_GROUP_THREADS = ACE_MAX_THREADS * 2;

static ACE_Atomic_Op<ACE_Thread_Mutex, int> run_count (0);

class Waiter_Task : public ACE_Task_Base
{
public:
  Waiter_Task (ACE_Thread_Manager* tm = 0)
    : ACE_Task_Base (tm) {}
  virtual int svc(void);
};

int
Waiter_Task::svc(void)
{
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("(%t|grp_id=%d) waiting for thread cancellation.\n"), this->grp_id ()));

  run_count++;

  // wait until canceled
  while (!ACE_Task_Base::thr_mgr ()->testcancel (ACE_OS::thr_self ()))
    ACE_OS::sleep (0);

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("(%t|grp_id=%d) thread cancelled.\n"), this->grp_id ()));

  run_count--;

  return 0;
}

#endif /* ACE_HAS_THREADS */

int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Task_Group_Test"));

#if defined (ACE_HAS_THREADS)

  ACE_thread_t thread_list[MAX_GROUP_THREADS] = {0};
  int group_id = -1;

  Waiter_Task waiter_task (ACE_Thread_Manager::instance ());

  // activate a single thread
  waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1);
  // get the assigned grp_id
  group_id = waiter_task.grp_id ();
  // attempt to add a thread -> this should fail without force_activate
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1) != 1)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have failed to add new thread.")));
  }
  // force addition of new thread
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // force addition of new thread ignoring specific group id
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1, ACE_DEFAULT_THREAD_PRIORITY, group_id+1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // we should now have 3 threads in group 'group_id'
  if (waiter_task.thr_mgr ()->thread_grp_list (group_id, &thread_list[0], MAX_GROUP_THREADS) != 3)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("Should have found 3 threads in group %d."), group_id));
  }

  // cancel all threads
  waiter_task.thr_mgr ()->cancel_all ();
  // wait for threads to exit cleanly
  while (waiter_task.thr_mgr ()->num_threads_in_task (&waiter_task) > 0)
    ACE_OS::sleep (0);

  // restart 2 threads reusing the group id
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 2) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to add new threads.")));
  }
  // attempt to add a thread -> this should fail without force_activate
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1) != 1)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have failed to add new thread.")));
  }
  // force addition of new thread
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // force addition of new thread ignoring specific group id
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1, ACE_DEFAULT_THREAD_PRIORITY, group_id+1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // we should now have 4 threads in group 'group_id'
  if (waiter_task.thr_mgr ()->thread_grp_list (group_id, &thread_list[0], MAX_GROUP_THREADS) != 4)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("Should have found 4 threads in group %d."), group_id));
  }

  // wait till the threads actually started up
  while (run_count != 4)
    ACE_OS::sleep (0);

  // change the group id of all threads of the task
  group_id += 1;
  waiter_task.grp_id (group_id);

  // we should still have 4 threads in group with new 'group_id'
  if (waiter_task.thr_mgr ()->thread_grp_list (group_id, &thread_list[0], MAX_GROUP_THREADS) != 4)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("Should have found 4 threads in group %d."), group_id));
  }

  // cancel all threads
  waiter_task.thr_mgr ()->cancel_all ();
  // wait for threads to exit cleanly
  while (waiter_task.thr_mgr ()->num_threads_in_task (&waiter_task) > 0)
    ACE_OS::sleep (0);

  // restart 3 threads using explicit new group id
  group_id = 33;
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 3, 0, ACE_DEFAULT_THREAD_PRIORITY, group_id) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to add new threads.")));
  }
  // attempt to add a thread -> this should fail without force_activate
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1) != 1)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have failed to add new thread.")));
  }
  // force addition of new thread
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // force addition of new thread ignoring specific group id
  if (waiter_task.activate (THR_NEW_LWP | THR_DETACHED, 1, 1, ACE_DEFAULT_THREAD_PRIORITY, group_id+1) != 0)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("ACE_Task_Base::activate should have succeeded to force addition of new thread.")));
  }
  // we should now have 5 threads in group 'group_id'
  if (waiter_task.thr_mgr ()->thread_grp_list (group_id, &thread_list[0], MAX_GROUP_THREADS) != 5)
  {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("Should have found 5 threads in group %d."), group_id));
  }

  // cancel all threads
  waiter_task.thr_mgr ()->cancel_all ();
  // wait for threads to exit cleanly
  while (waiter_task.thr_mgr ()->num_threads_in_task (&waiter_task) > 0)
    ACE_OS::sleep (0);

#else
  ACE_ERROR ((LM_INFO,
              ACE_TEXT ("threads not supported on this platform\n")));
#endif /* ACE_HAS_THREADS */
  ACE_END_TEST;
  return 0;
}