• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Copyright (C) 2011 Vicente J. Botet Escriba
10 //
11 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
12 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 
14 // <boost/thread/condition_variable>
15 
16 // class condition_variable;
17 
18 // condition_variable(const condition_variable&) = delete;
19 
20 #include <boost/thread/condition_variable.hpp>
21 #include <boost/thread/mutex.hpp>
22 #include <boost/thread/thread.hpp>
23 #include <boost/detail/lightweight_test.hpp>
24 #include <cassert>
25 #include <iostream>
26 #include "../../../timming.hpp"
27 
28 #if defined BOOST_THREAD_USES_CHRONO
29 typedef boost::chrono::milliseconds milliseconds;
30 typedef boost::chrono::nanoseconds nanoseconds;
31 typedef boost::chrono::milliseconds ms;
32 typedef boost::chrono::nanoseconds ns;
33 struct Clock
34 {
35   typedef boost::chrono::milliseconds duration;
36   typedef duration::rep rep;
37   typedef duration::period period;
38   typedef boost::chrono::time_point<Clock> time_point;
39   static const bool is_steady = true;
40 
nowClock41   static time_point now()
42   {
43     using namespace boost::chrono;
44     return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch()));
45   }
46 };
47 
48 class Pred
49 {
50   int& i_;
51 public:
Pred(int & i)52   explicit Pred(int& i) :
53     i_(i)
54   {
55   }
56 
operator ()()57   bool operator()()
58   {
59     return i_ != 0;
60   }
61 };
62 
63 boost::condition_variable cv;
64 boost::mutex mut;
65 
66 int test1 = 0;
67 int test2 = 0;
68 
69 int runs = 0;
70 
71 const ms max_diff(BOOST_THREAD_TEST_TIME_MS);
72 
f()73 void f()
74 {
75   try {
76     boost::unique_lock<boost::mutex> lk(mut);
77     assert(test2 == 0);
78     test1 = 1;
79     cv.notify_one();
80     Clock::time_point t0 = Clock::now();
81     Clock::time_point t = t0 + Clock::duration(250);
82     bool r = cv.wait_until(lk, t, Pred(test2));
83     Clock::time_point t1 = Clock::now();
84     if (runs == 0)
85     {
86       assert(t1 - t0 < max_diff);
87       assert(test2 != 0);
88       assert(r);
89     }
90     else
91     {
92       const nanoseconds d = t1 - t0 - milliseconds(250);
93       std::cout << "diff= " << d.count() << std::endl;
94       std::cout << "max_diff= " << max_diff.count() << std::endl;
95       assert(d < max_diff);
96       assert(test2 == 0);
97       assert(!r);
98     }
99     ++runs;
100   } catch(...) {
101     std::cout << "ERROR exception" << __LINE__ << std::endl;
102     assert(false);
103   }
104 }
105 
main()106 int main()
107 {
108   try
109   {
110     boost::unique_lock<boost::mutex> lk(mut);
111     boost::thread t(f);
112     BOOST_TEST(test1 == 0);
113     while (test1 == 0)
114       cv.wait(lk);
115     BOOST_TEST(test1 != 0);
116     test2 = 1;
117     lk.unlock();
118     cv.notify_one();
119     t.join();
120   } catch(...) {
121     BOOST_TEST(false);
122     std::cout << "ERROR exception" << __LINE__ << std::endl;
123   }
124   test1 = 0;
125   test2 = 0;
126   try
127   {
128     boost::unique_lock<boost::mutex> lk(mut);
129     boost::thread t(f);
130     BOOST_TEST(test1 == 0);
131     while (test1 == 0)
132       cv.wait(lk);
133     BOOST_TEST(test1 != 0);
134     lk.unlock();
135     t.join();
136   } catch(...) {
137     BOOST_TEST(false);
138     std::cout << "ERROR exception" << __LINE__ << std::endl;
139   }
140 
141   return boost::report_errors();
142 }
143 
144 #else
145 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
146 #endif
147