1 // Copyright (C) 2001-2003
3 // Copyright (C) 2007 Anthony Williams
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #define BOOST_THREAD_VERSION 2
9 #define BOOST_THREAD_PROVIDES_INTERRUPTIONS
10 #define BOOST_TEST_MODULE Boost.Threads: tss test suite
12 #include <boost/thread/detail/config.hpp>
13 #include <boost/predef/platform.h>
15 #include <boost/thread/tss.hpp>
16 #include <boost/thread/mutex.hpp>
17 #include <boost/thread/thread.hpp>
19 #include <boost/test/unit_test.hpp>
25 #if defined(BOOST_THREAD_PLATFORM_WIN32)
26 #define WIN32_LEAN_AND_MEAN
30 boost::mutex check_mutex
;
31 boost::mutex tss_mutex
;
32 int tss_instances
= 0;
39 boost::unique_lock
<boost::mutex
> lock(tss_mutex
);
46 boost::unique_lock
<boost::mutex
> lock(tss_mutex
);
52 boost::thread_specific_ptr
<tss_value_t
> tss_value
;
54 void test_tss_thread()
56 tss_value
.reset(new tss_value_t());
57 for (int i
=0; i
<1000; ++i
)
59 int& n
= tss_value
->value
;
60 // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to
61 // be thread safe. Must evaluate further.
64 boost::unique_lock
<boost::mutex
> lock(check_mutex
);
65 BOOST_CHECK_EQUAL(n
, i
);
73 #if defined(BOOST_THREAD_PLATFORM_WIN32)
74 #if BOOST_PLAT_WINDOWS_RUNTIME
75 typedef std::shared_ptr
<std::thread
> native_thread_t
;
77 BOOST_AUTO_TEST_CASE(test_tss_thread_native
)
82 native_thread_t
create_native_thread()
84 return std::make_shared
<std::thread
>(test_tss_thread_native
);
87 void join_native_thread(native_thread_t thread
)
93 typedef HANDLE native_thread_t
;
95 DWORD WINAPI
test_tss_thread_native(LPVOID
/*lpParameter*/)
101 native_thread_t
create_native_thread(void)
103 native_thread_t
const res
=CreateThread(
104 0, //security attributes (0 = not inheritable)
105 0, //stack size (0 = default)
106 &test_tss_thread_native
, //function to execute
107 0, //parameter to pass to function
108 0, //creation flags (0 = run immediately)
109 0 //thread id (0 = thread id not returned)
115 void join_native_thread(native_thread_t thread
)
117 DWORD res
= WaitForSingleObject(thread
, INFINITE
);
118 BOOST_CHECK(res
== WAIT_OBJECT_0
);
120 res
= CloseHandle(thread
);
121 BOOST_CHECK(SUCCEEDED(res
));
124 #elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
125 typedef pthread_t native_thread_t
;
129 void* test_tss_thread_native(void* )
136 native_thread_t
create_native_thread()
138 native_thread_t thread_handle
;
140 int const res
= pthread_create(&thread_handle
, 0, &test_tss_thread_native
, 0);
142 return thread_handle
;
145 void join_native_thread(native_thread_t thread
)
148 int const res
=pthread_join(thread
,&result
);
158 const int NUMTHREADS
=5;
159 boost::thread_group threads
;
162 for (int i
=0; i
<NUMTHREADS
; ++i
)
163 threads
.create_thread(&test_tss_thread
);
168 threads
.interrupt_all();
175 << "tss_instances = " << tss_instances
176 << "; tss_total = " << tss_total
180 BOOST_CHECK_EQUAL(tss_instances
, 0);
181 BOOST_CHECK_EQUAL(tss_total
, 5);
186 native_thread_t thread1
= create_native_thread();
187 native_thread_t thread2
= create_native_thread();
188 native_thread_t thread3
= create_native_thread();
189 native_thread_t thread4
= create_native_thread();
190 native_thread_t thread5
= create_native_thread();
192 join_native_thread(thread5
);
193 join_native_thread(thread4
);
194 join_native_thread(thread3
);
195 join_native_thread(thread2
);
196 join_native_thread(thread1
);
199 << "tss_instances = " << tss_instances
200 << "; tss_total = " << tss_total
204 // The following is not really an error. TSS cleanup support still is available for boost threads.
205 // Also this usually will be triggered only when bound to the static version of thread lib.
206 // 2006-10-02 Roland Schwarz
207 //BOOST_CHECK_EQUAL(tss_instances, 0);
208 #if !defined(__MINGW32__)
209 // This fails on MinGW, when using the static lib
210 BOOST_CHECK_MESSAGE(tss_instances
== 0, "Support of automatic tss cleanup for native threading API not available");
212 BOOST_CHECK_EQUAL(tss_total
, 5);
215 BOOST_AUTO_TEST_CASE(test_tss
)
217 timed_test(&do_test_tss
, 2);
221 bool tss_void_cleanup_called
=false;
223 void tss_void_custom_cleanup(void* d
)
225 std::cout
<< d
<< std::endl
;
226 delete reinterpret_cast<tss_value_t
*>(d
);
227 tss_void_cleanup_called
=true;
230 boost::thread_specific_ptr
<void> tss_void(tss_void_custom_cleanup
);
232 void test_tss_void_thread()
234 tss_void
.reset(new tss_value_t());
235 for (int i
=0; i
<10; ++i
)
237 int& n
= static_cast<tss_value_t
*>(tss_value
.get())->value
;
239 // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to
240 // be thread safe. Must evaluate further.
243 boost::unique_lock
<boost::mutex
> lock(check_mutex
);
244 BOOST_CHECK_EQUAL(n
, i
);
249 void do_test_tss_void()
254 const int NUMTHREADS
=5;
255 boost::thread_group threads
;
258 for (int i
=0; i
<NUMTHREADS
; ++i
)
259 threads
.create_thread(&test_tss_void_thread
);
264 threads
.interrupt_all();
271 << "tss_instances = " << tss_instances
272 << "; tss_total = " << tss_total
276 BOOST_CHECK_EQUAL(tss_instances
, 0);
277 BOOST_CHECK_EQUAL(tss_total
, 5);
279 // tss_instances = 0;
282 // native_thread_t thread1 = create_native_thread();
283 // native_thread_t thread2 = create_native_thread();
284 // native_thread_t thread3 = create_native_thread();
285 // native_thread_t thread4 = create_native_thread();
286 // native_thread_t thread5 = create_native_thread();
288 // join_native_thread(thread5);
289 // join_native_thread(thread4);
290 // join_native_thread(thread3);
291 // join_native_thread(thread2);
292 // join_native_thread(thread1);
295 // << "tss_instances = " << tss_instances
296 // << "; tss_total = " << tss_total
298 // std::cout.flush();
300 // // The following is not really an error. TSS cleanup support still is available for boost threads.
301 // // Also this usually will be triggered only when bound to the static version of thread lib.
302 // // 2006-10-02 Roland Schwarz
303 // //BOOST_CHECK_EQUAL(tss_instances, 0);
304 // BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available");
305 // BOOST_CHECK_EQUAL(tss_total, 5);
308 //BOOST_AUTO_TEST_CASE(test_tss_void)
310 // timed_test(&do_test_tss_void, 2);
314 boost::thread_specific_ptr
<void> tss_void_with_cleanup(tss_void_custom_cleanup
);
316 void tss_void_thread_with_custom_cleanup()
318 tss_void_with_cleanup
.reset(new tss_value_t
);
321 void do_test_tss_void_with_custom_cleanup()
323 boost::thread
t(tss_void_thread_with_custom_cleanup
);
335 BOOST_CHECK(tss_void_cleanup_called
);
339 BOOST_AUTO_TEST_CASE(test_tss_void_with_custom_cleanup
)
341 timed_test(&do_test_tss_void_with_custom_cleanup
, 2);
345 bool tss_cleanup_called
=false;
350 void tss_custom_cleanup(Dummy
* d
)
353 tss_cleanup_called
=true;
356 boost::thread_specific_ptr
<Dummy
> tss_with_cleanup(tss_custom_cleanup
);
358 void tss_thread_with_custom_cleanup()
360 tss_with_cleanup
.reset(new Dummy
);
363 void do_test_tss_with_custom_cleanup()
365 boost::thread
t(tss_thread_with_custom_cleanup
);
377 BOOST_CHECK(tss_cleanup_called
);
381 BOOST_AUTO_TEST_CASE(test_tss_with_custom_cleanup
)
383 timed_test(&do_test_tss_with_custom_cleanup
, 2);
386 Dummy
* tss_object
=new Dummy
;
388 void tss_thread_with_custom_cleanup_and_release()
390 tss_with_cleanup
.reset(tss_object
);
391 tss_with_cleanup
.release();
394 void do_test_tss_does_no_cleanup_after_release()
396 tss_cleanup_called
=false;
397 boost::thread
t(tss_thread_with_custom_cleanup_and_release
);
409 BOOST_CHECK(!tss_cleanup_called
);
410 if(!tss_cleanup_called
)
416 struct dummy_class_tracks_deletions
418 static unsigned deletions
;
420 ~dummy_class_tracks_deletions()
427 unsigned dummy_class_tracks_deletions::deletions
=0;
429 boost::thread_specific_ptr
<dummy_class_tracks_deletions
> tss_with_null_cleanup(NULL
);
431 void tss_thread_with_null_cleanup(dummy_class_tracks_deletions
* delete_tracker
)
433 tss_with_null_cleanup
.reset(delete_tracker
);
436 void do_test_tss_does_no_cleanup_with_null_cleanup_function()
438 dummy_class_tracks_deletions
* delete_tracker
=new dummy_class_tracks_deletions
;
439 boost::thread
t(tss_thread_with_null_cleanup
,delete_tracker
);
451 BOOST_CHECK(!dummy_class_tracks_deletions::deletions
);
452 if(!dummy_class_tracks_deletions::deletions
)
454 delete delete_tracker
;
458 BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_after_release
)
460 timed_test(&do_test_tss_does_no_cleanup_after_release
, 2);
463 BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function
)
465 timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function
, 2);
468 void thread_with_local_tss_ptr()
471 boost::thread_specific_ptr
<Dummy
> local_tss(tss_custom_cleanup
);
473 local_tss
.reset(new Dummy
);
475 BOOST_CHECK(tss_cleanup_called
);
476 tss_cleanup_called
=false;
480 BOOST_AUTO_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed
)
482 boost::thread
t(thread_with_local_tss_ptr
);
484 BOOST_CHECK(!tss_cleanup_called
);
487 BOOST_AUTO_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer
)
489 boost::thread_specific_ptr
<Dummy
> local_tss(tss_custom_cleanup
);
490 local_tss
.reset(new Dummy
);
491 tss_cleanup_called
=false;
493 BOOST_CHECK(tss_cleanup_called
);
494 tss_cleanup_called
=false;
495 local_tss
.reset(new Dummy
);
496 BOOST_CHECK(!tss_cleanup_called
);
499 //BOOST_AUTO_TEST_CASE(test_tss_at_the_same_adress)
501 // for(int i=0; i<2; i++)
503 // boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
504 // local_tss.reset(new Dummy);
505 // tss_cleanup_called=false;
506 // BOOST_CHECK(tss_cleanup_called);
507 // tss_cleanup_called=false;
508 // BOOST_CHECK(!tss_cleanup_called);