1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <IceUtil/IceUtil.h>
6 #include <IceUtil/CountDownLatch.h>
7
8 #include <CountDownLatchTest.h>
9 #include <TestHelper.h>
10
11 using namespace std;
12 using namespace IceUtil;
13 using namespace IceUtilInternal;
14
15 static const string testName("countDownLatch");
16
17 static const int magic = 0xbeef;
18
19 class CountDownLatchTestThread : public Thread
20 {
21 public:
22
CountDownLatchTestThread(CountDownLatch & latch,int & val,bool takeOne)23 CountDownLatchTestThread(CountDownLatch& latch, int& val, bool takeOne) :
24 _latch(latch),
25 _val(val),
26 _takeOne(takeOne)
27 {
28 }
29
run()30 virtual void run()
31 {
32
33 if(_takeOne)
34 {
35 _latch.countDown();
36 }
37
38 if(_latch.getCount() == 0)
39 {
40 test(_val == magic);
41 }
42
43 _latch.await();
44 test(_latch.getCount() == 0);
45 test(_val == magic);
46 }
47
48 private:
49
50 CountDownLatch& _latch;
51 int& _val;
52 bool _takeOne;
53 };
54
CountDownLatchTest()55 CountDownLatchTest::CountDownLatchTest() :
56 TestBase(testName)
57 {
58 }
59
60 void
run()61 CountDownLatchTest::run()
62 {
63 const int fullCount = 11;
64
65 int val = 0xabcd;
66
67 CountDownLatch latch(fullCount);
68 test(latch.getCount() == fullCount);
69
70 const int wave1Count = 6;
71
72 int i = 0;
73 ThreadPtr t1[wave1Count];
74 for(i = 0; i < wave1Count; i++)
75 {
76 t1[i] = new CountDownLatchTestThread(latch, val, false);
77 t1[i]->start();
78 }
79
80 //
81 // Sleep a little bit, and check count
82 //
83 ThreadControl::sleep(Time::seconds(1));
84 test(latch.getCount() == fullCount);
85
86 //
87 // Let's count down all except 1
88 //
89 ThreadPtr t2[fullCount - 1];
90 for(i = 0; i < fullCount - 1; i++)
91 {
92 t2[i] = new CountDownLatchTestThread(latch, val, true);
93 t2[i]->start();
94 }
95
96 //
97 // Sleep until count == 1
98 //
99 do
100 {
101 ThreadControl::sleep(Time::milliSeconds(100));
102
103 for(i = 0; i < wave1Count; i++)
104 {
105 test(t1[i]->isAlive());
106 }
107
108 for(i = 0; i < fullCount - 1; i++)
109 {
110 test(t2[i]->isAlive());
111 }
112
113 } while(latch.getCount() > 1);
114
115 //
116 // Set val and release last count
117 //
118 val = magic;
119 latch.countDown();
120 test(latch.getCount() == 0);
121
122 //
123 // Join them all
124 //
125 for(i = 0; i < wave1Count; i++)
126 {
127 t1[i]->getThreadControl().join();
128 }
129
130 for(i = 0; i < fullCount - 1; i++)
131 {
132 t2[i]->getThreadControl().join();
133 }
134
135 test(latch.getCount() == 0);
136
137 const int wave2Count = 4;
138 ThreadPtr t3[wave2Count];
139 for(i = 0; i < wave2Count; i++)
140 {
141 t3[i] = new CountDownLatchTestThread(latch, val, true);
142 t3[i]->start();
143 }
144 test(latch.getCount() == 0);
145
146 for(i = 0; i < wave2Count; i++)
147 {
148 t3[i]->getThreadControl().join();
149 }
150 test(latch.getCount() == 0);
151 }
152