summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/thread/test/test_once.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/thread/test/test_once.cpp')
-rw-r--r--src/boost/libs/thread/test/test_once.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/boost/libs/thread/test/test_once.cpp b/src/boost/libs/thread/test/test_once.cpp
new file mode 100644
index 000000000..3103f1c23
--- /dev/null
+++ b/src/boost/libs/thread/test/test_once.cpp
@@ -0,0 +1,192 @@
+// (C) Copyright 2006-7 Anthony Williams
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_THREAD_VERSION 2
+#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#define BOOST_TEST_MODULE Boost.Threads: once test suite
+
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/once.hpp>
+#include <iostream>
+
+#include <boost/thread/detail/log.hpp>
+
+boost::once_flag flag=BOOST_ONCE_INIT;
+int var_to_init=0;
+boost::mutex m;
+
+void initialize_variable()
+{
+ // ensure that if multiple threads get in here, they are serialized, so we can see the effect
+ boost::unique_lock<boost::mutex> lock(m);
+ ++var_to_init;
+}
+
+
+void call_once_thread()
+{
+ unsigned const loop_count=100;
+ int my_once_value=0;
+ for(unsigned i=0;i<loop_count;++i)
+ {
+ boost::call_once(flag, &initialize_variable);
+ my_once_value=var_to_init;
+ if(my_once_value!=1)
+ {
+ break;
+ }
+ }
+ boost::unique_lock<boost::mutex> lock(m);
+ BOOST_CHECK_EQUAL(my_once_value, 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_call_once)
+{
+ BOOST_DETAIL_THREAD_LOG;
+
+ unsigned const num_threads=20;
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<num_threads;++i)
+ {
+ group.create_thread(&call_once_thread);
+ }
+ group.join_all();
+ }
+ catch(...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(var_to_init,1);
+}
+
+int var_to_init_with_functor=0;
+
+struct increment_value
+{
+ int* value;
+ explicit increment_value(int* value_):
+ value(value_)
+ {}
+
+ void operator()() const
+ {
+ boost::unique_lock<boost::mutex> lock(m);
+ ++(*value);
+ }
+};
+
+void call_once_with_functor()
+{
+ unsigned const loop_count=100;
+ int my_once_value=0;
+ static boost::once_flag functor_flag=BOOST_ONCE_INIT;
+ for(unsigned i=0;i<loop_count;++i)
+ {
+ boost::call_once(functor_flag, increment_value(&var_to_init_with_functor));
+ my_once_value=var_to_init_with_functor;
+ if(my_once_value!=1)
+ {
+ break;
+ }
+ }
+ boost::unique_lock<boost::mutex> lock(m);
+ BOOST_CHECK_EQUAL(my_once_value, 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_call_once_arbitrary_functor)
+{
+ BOOST_DETAIL_THREAD_LOG;
+
+ unsigned const num_threads=20;
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<num_threads;++i)
+ {
+ group.create_thread(&call_once_with_functor);
+ }
+ group.join_all();
+ }
+ catch(...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(var_to_init_with_functor,1);
+}
+
+
+struct throw_before_third_pass
+{
+ struct my_exception
+ {};
+
+ static unsigned pass_counter;
+
+ void operator()() const
+ {
+ boost::unique_lock<boost::mutex> lock(m);
+ ++pass_counter;
+ if(pass_counter<3)
+ {
+ throw my_exception();
+ }
+ }
+};
+
+unsigned throw_before_third_pass::pass_counter=0;
+unsigned exception_counter=0;
+
+void call_once_with_exception()
+{
+ static boost::once_flag functor_flag=BOOST_ONCE_INIT;
+ try
+ {
+ boost::call_once(functor_flag, throw_before_third_pass());
+ }
+ catch(throw_before_third_pass::my_exception)
+ {
+ boost::unique_lock<boost::mutex> lock(m);
+ ++exception_counter;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_call_once_retried_on_exception)
+{
+ BOOST_DETAIL_THREAD_LOG;
+ unsigned const num_threads=20;
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<num_threads;++i)
+ {
+ group.create_thread(&call_once_with_exception);
+ }
+ group.join_all();
+ }
+ catch(...)
+ {
+ group.interrupt_all();
+ group.join_all();
+ throw;
+ }
+
+ BOOST_CHECK_EQUAL(throw_before_third_pass::pass_counter,3u);
+ BOOST_CHECK_EQUAL(exception_counter,2u);
+}
+
+