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