• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2013 Vicente J. Botet Escriba
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // <boost/thread/future.hpp>
7 
8 // class future<R>
9 
10 // R future::get_or(R&&);
11 // R& future<R&>::get_or(R&);
12 
13 #define BOOST_THREAD_VERSION 4
14 //#define BOOST_THREAD_USES_LOG
15 #define BOOST_THREAD_USES_LOG_THREAD_ID
16 #include <boost/thread/detail/log.hpp>
17 
18 #include <boost/thread/future.hpp>
19 #include <boost/thread/thread.hpp>
20 #include <boost/core/ref.hpp>
21 #include <boost/detail/lightweight_test.hpp>
22 
23 #if defined BOOST_THREAD_USES_CHRONO
24 
25 #ifdef BOOST_MSVC
26 #pragma warning(disable: 4127) // conditional expression is constant
27 #endif
28 
29 namespace boost
30 {
31 template <typename T>
32 struct wrap
33 {
wrapboost::wrap34   wrap(T const& v) : value(v){}
35   T value;
36 
37 };
38 
39 template <typename T>
make_exception_ptr(T v)40 exception_ptr make_exception_ptr(T v) {
41   return copy_exception(wrap<T>(v));
42 }
43 }
44 
func1(boost::promise<int> p)45 void func1(boost::promise<int> p)
46 {
47     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
48     p.set_value(3);
49 }
50 
func2(boost::promise<int> p)51 void func2(boost::promise<int> p)
52 {
53     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
54     p.set_exception(boost::make_exception_ptr(3));
55 }
56 
57 int j = 0;
58 
func3(boost::promise<int &> p)59 void func3(boost::promise<int&> p)
60 {
61     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
62     j = 5;
63     p.set_value(j);
64 }
65 
func4(boost::promise<int &> p)66 void func4(boost::promise<int&> p)
67 {
68     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
69     p.set_exception(boost::make_exception_ptr(3.5));
70 }
71 
func5(boost::promise<void> p)72 void func5(boost::promise<void> p)
73 {
74     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
75     p.set_value();
76 }
77 
func6(boost::promise<void> p)78 void func6(boost::promise<void> p)
79 {
80     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
81     p.set_exception(boost::make_exception_ptr(4));
82 }
83 
84 
main()85 int main()
86 {
87   BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
88   {
89       typedef int T;
90       {
91           boost::promise<T> p;
92           boost::future<T> f = p.get_future();
93 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
94            boost::thread(func1, boost::move(p)).detach();
95 #else
96            p.set_value(3);
97 #endif
98           BOOST_TEST(f.valid());
99           BOOST_TEST(f.get_or(4) == 3);
100 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
101           BOOST_TEST(!f.valid());
102 #endif
103       }
104       BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
105       {
106           boost::promise<T> p;
107           BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
108           boost::future<T> f = p.get_future();
109           BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
110 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
111           boost::thread(func2, boost::move(p)).detach();
112 #else
113           p.set_exception(boost::make_exception_ptr(3));
114 #endif
115           BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
116           try
117           {
118             BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
119               BOOST_TEST(f.valid());
120               BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
121               BOOST_TEST(f.get_or(4) == 4);
122               BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
123           }
124           catch (...)
125           {
126             BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
127             BOOST_TEST(false);
128           }
129 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
130           BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
131           BOOST_TEST(!f.valid());
132 #endif
133           BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
134       }
135   }
136   BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
137   {
138       typedef int& T;
139       {
140           boost::promise<T> p;
141           boost::future<T> f = p.get_future();
142 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
143           boost::thread(func3, boost::move(p)).detach();
144 #else
145           int j=5;
146           p.set_value(j);
147 #endif
148           BOOST_TEST(f.valid());
149           int k=4;
150           BOOST_TEST(f.get_or(boost::ref(k)) == 5);
151 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
152           BOOST_TEST(!f.valid());
153 #endif
154       }
155       BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
156       {
157           boost::promise<T> p;
158           boost::future<T> f = p.get_future();
159 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
160           boost::thread(func4, boost::move(p)).detach();
161 #else
162           p.set_exception(boost::make_exception_ptr(3.5));
163 #endif
164           try
165           {
166               BOOST_TEST(f.valid());
167               int j=4;
168               BOOST_TEST(f.get_or(boost::ref(j)) == 4);
169           }
170           catch (...)
171           {
172             BOOST_TEST(false);
173           }
174 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
175           BOOST_TEST(!f.valid());
176 #endif
177       }
178   }
179   BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
180 
181 
182   return boost::report_errors();
183 }
184 
185 #else
186 #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
187 #endif
188