From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/boost/libs/thread/example/Jamfile.v2 | 23 + .../libs/thread/example/ba_externallly_locked.cpp | 120 ++++ src/boost/libs/thread/example/condition.cpp | 91 +++ src/boost/libs/thread/example/default_executor.cpp | 61 ++ src/boost/libs/thread/example/executor.cpp | 207 ++++++ src/boost/libs/thread/example/fib_task_region.cpp | 91 +++ .../libs/thread/example/future_fallback_to.cpp | 161 +++++ src/boost/libs/thread/example/future_then.cpp | 137 ++++ src/boost/libs/thread/example/future_unwrap.cpp | 92 +++ src/boost/libs/thread/example/future_when_all.cpp | 330 +++++++++ .../libs/thread/example/generic_executor_ref.cpp | 163 +++++ src/boost/libs/thread/example/lambda_future.cpp | 80 +++ src/boost/libs/thread/example/make_future.cpp | 154 +++++ src/boost/libs/thread/example/monitor.cpp | 113 ++++ src/boost/libs/thread/example/mutex.cpp | 47 ++ src/boost/libs/thread/example/not_interleaved.cpp | 63 ++ src/boost/libs/thread/example/not_interleaved2.cpp | 61 ++ src/boost/libs/thread/example/once.cpp | 39 ++ .../libs/thread/example/parallel_accumulate.cpp | 102 +++ .../libs/thread/example/parallel_quick_sort.cpp | 110 +++ .../thread/example/perf_condition_variable.cpp | 237 +++++++ .../libs/thread/example/perf_shared_mutex.cpp | 72 ++ .../libs/thread/example/producer_consumer.cpp | 147 ++++ .../libs/thread/example/producer_consumer2.cpp | 150 +++++ .../thread/example/producer_consumer_bounded.cpp | 146 ++++ src/boost/libs/thread/example/recursive_mutex.cpp | 49 ++ src/boost/libs/thread/example/scoped_thread.cpp | 83 +++ src/boost/libs/thread/example/serial_executor.cpp | 107 +++ .../libs/thread/example/serial_executor_cont.cpp | 113 ++++ src/boost/libs/thread/example/shared_monitor.cpp | 144 ++++ src/boost/libs/thread/example/shared_mutex.cpp | 746 +++++++++++++++++++++ src/boost/libs/thread/example/starvephil.cpp | 187 ++++++ .../libs/thread/example/std_scoped_thread.cpp | 112 ++++ src/boost/libs/thread/example/std_thread_guard.cpp | 66 ++ src/boost/libs/thread/example/strict_lock.cpp | 40 ++ .../libs/thread/example/synchronized_person.cpp | 282 ++++++++ .../libs/thread/example/synchronized_value.cpp | 147 ++++ src/boost/libs/thread/example/tennis.cpp | 137 ++++ src/boost/libs/thread/example/this_executor.cpp | 85 +++ src/boost/libs/thread/example/thread.cpp | 37 + src/boost/libs/thread/example/thread_group.cpp | 73 ++ src/boost/libs/thread/example/thread_guard.cpp | 58 ++ src/boost/libs/thread/example/thread_pool.cpp | 78 +++ src/boost/libs/thread/example/tss.cpp | 37 + src/boost/libs/thread/example/user_scheduler.cpp | 79 +++ src/boost/libs/thread/example/with_lock_guard.cpp | 53 ++ src/boost/libs/thread/example/xtime.cpp | 18 + 47 files changed, 5728 insertions(+) create mode 100644 src/boost/libs/thread/example/Jamfile.v2 create mode 100644 src/boost/libs/thread/example/ba_externallly_locked.cpp create mode 100644 src/boost/libs/thread/example/condition.cpp create mode 100644 src/boost/libs/thread/example/default_executor.cpp create mode 100644 src/boost/libs/thread/example/executor.cpp create mode 100644 src/boost/libs/thread/example/fib_task_region.cpp create mode 100644 src/boost/libs/thread/example/future_fallback_to.cpp create mode 100644 src/boost/libs/thread/example/future_then.cpp create mode 100644 src/boost/libs/thread/example/future_unwrap.cpp create mode 100644 src/boost/libs/thread/example/future_when_all.cpp create mode 100644 src/boost/libs/thread/example/generic_executor_ref.cpp create mode 100644 src/boost/libs/thread/example/lambda_future.cpp create mode 100644 src/boost/libs/thread/example/make_future.cpp create mode 100644 src/boost/libs/thread/example/monitor.cpp create mode 100644 src/boost/libs/thread/example/mutex.cpp create mode 100644 src/boost/libs/thread/example/not_interleaved.cpp create mode 100644 src/boost/libs/thread/example/not_interleaved2.cpp create mode 100644 src/boost/libs/thread/example/once.cpp create mode 100644 src/boost/libs/thread/example/parallel_accumulate.cpp create mode 100644 src/boost/libs/thread/example/parallel_quick_sort.cpp create mode 100644 src/boost/libs/thread/example/perf_condition_variable.cpp create mode 100644 src/boost/libs/thread/example/perf_shared_mutex.cpp create mode 100644 src/boost/libs/thread/example/producer_consumer.cpp create mode 100644 src/boost/libs/thread/example/producer_consumer2.cpp create mode 100644 src/boost/libs/thread/example/producer_consumer_bounded.cpp create mode 100644 src/boost/libs/thread/example/recursive_mutex.cpp create mode 100644 src/boost/libs/thread/example/scoped_thread.cpp create mode 100644 src/boost/libs/thread/example/serial_executor.cpp create mode 100644 src/boost/libs/thread/example/serial_executor_cont.cpp create mode 100644 src/boost/libs/thread/example/shared_monitor.cpp create mode 100644 src/boost/libs/thread/example/shared_mutex.cpp create mode 100644 src/boost/libs/thread/example/starvephil.cpp create mode 100644 src/boost/libs/thread/example/std_scoped_thread.cpp create mode 100644 src/boost/libs/thread/example/std_thread_guard.cpp create mode 100644 src/boost/libs/thread/example/strict_lock.cpp create mode 100644 src/boost/libs/thread/example/synchronized_person.cpp create mode 100644 src/boost/libs/thread/example/synchronized_value.cpp create mode 100644 src/boost/libs/thread/example/tennis.cpp create mode 100644 src/boost/libs/thread/example/this_executor.cpp create mode 100644 src/boost/libs/thread/example/thread.cpp create mode 100644 src/boost/libs/thread/example/thread_group.cpp create mode 100644 src/boost/libs/thread/example/thread_guard.cpp create mode 100644 src/boost/libs/thread/example/thread_pool.cpp create mode 100644 src/boost/libs/thread/example/tss.cpp create mode 100644 src/boost/libs/thread/example/user_scheduler.cpp create mode 100644 src/boost/libs/thread/example/with_lock_guard.cpp create mode 100644 src/boost/libs/thread/example/xtime.cpp (limited to 'src/boost/libs/thread/example') diff --git a/src/boost/libs/thread/example/Jamfile.v2 b/src/boost/libs/thread/example/Jamfile.v2 new file mode 100644 index 000000000..bfc8a59b3 --- /dev/null +++ b/src/boost/libs/thread/example/Jamfile.v2 @@ -0,0 +1,23 @@ +# Copyright (C) 2001-2003 +# William E. Kempf +# +# 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) + +project boost/thread/example + : requirements ../build//boost_thread multi + ; + + +exe monitor : monitor.cpp ; +exe starvephil : starvephil.cpp ; +exe tennis : tennis.cpp ; +exe condition : condition.cpp ; +exe mutex : mutex.cpp ; +exe once : once.cpp ; +exe recursive_mutex : recursive_mutex.cpp ; +exe thread : thread.cpp ; +exe thread_group : thread_group.cpp ; +exe tss : tss.cpp ; +exe xtime : xtime.cpp ; + diff --git a/src/boost/libs/thread/example/ba_externallly_locked.cpp b/src/boost/libs/thread/example/ba_externallly_locked.cpp new file mode 100644 index 000000000..e93876769 --- /dev/null +++ b/src/boost/libs/thread/example/ba_externallly_locked.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2012 Vicente Botet +// +// 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 4 + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(disable: 4355) // 'this' : used in base member initializer list +#endif + +using namespace boost; + +class BankAccount +{ + int balance_; +public: + void Deposit(int amount) + { + balance_ += amount; + } + void Withdraw(int amount) + { + balance_ -= amount; + } + int GetBalance() + { + return balance_; + } +}; + +//[AccountManager +class AccountManager: public basic_lockable_adapter +{ +public: + typedef basic_lockable_adapter lockable_base_type; + AccountManager() : + lockable_base_type(), checkingAcct_(*this), savingsAcct_(*this) + { + } + inline void Checking2Savings(int amount); + inline void AMoreComplicatedChecking2Savings(int amount); +private: + /*<-*/ + bool some_condition() + { + return true; + } /*->*/ + externally_locked checkingAcct_; + externally_locked savingsAcct_; +}; +//] + +//[Checking2Savings +void AccountManager::Checking2Savings(int amount) +{ + strict_lock guard(*this); + checkingAcct_.get(guard).Withdraw(amount); + savingsAcct_.get(guard).Deposit(amount); +} +//] + +//#if DO_NOT_COMPILE +////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE +//void AccountManager::AMoreComplicatedChecking2Savings(int amount) { +// unique_lock guard(*this); +// if (some_condition()) { +// guard.lock(); +// } +// checkingAcct_.get(guard).Withdraw(amount); +// savingsAcct_.get(guard).Deposit(amount); +// guard1.unlock(); +//} +////] +//#elif DO_NOT_COMPILE_2 +////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2 +//void AccountManager::AMoreComplicatedChecking2Savings(int amount) { +// unique_lock guard1(*this); +// if (some_condition()) { +// guard1.lock(); +// } +// { +// strict_lock guard(guard1); +// checkingAcct_.get(guard).Withdraw(amount); +// savingsAcct_.get(guard).Deposit(amount); +// } +// guard1.unlock(); +//} +////] +//#else +////[AMoreComplicatedChecking2Savings +void AccountManager::AMoreComplicatedChecking2Savings(int amount) { + unique_lock guard1(*this); + if (some_condition()) { + guard1.lock(); + } + { + nested_strict_lock > guard(guard1); + checkingAcct_.get(guard).Withdraw(amount); + savingsAcct_.get(guard).Deposit(amount); + } + guard1.unlock(); +} +////] +//#endif + +int main() +{ + AccountManager mgr; + mgr.Checking2Savings(100); + return 0; +} + diff --git a/src/boost/libs/thread/example/condition.cpp b/src/boost/libs/thread/example/condition.cpp new file mode 100644 index 000000000..a747f9e45 --- /dev/null +++ b/src/boost/libs/thread/example/condition.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#include +#include +#include +#include +#include +#include "../test/remove_error_code_unused_warning.hpp" + +class bounded_buffer : private boost::noncopyable +{ +public: + typedef boost::unique_lock lock; + + bounded_buffer(int n) : boost::noncopyable(), begin(0), end(0), buffered(0), circular_buf(n) { } + + void send (int m) { + lock lk(monitor); + while (buffered == circular_buf.size()) + buffer_not_full.wait(lk); + circular_buf[end] = m; + end = (end+1) % circular_buf.size(); + ++buffered; + buffer_not_empty.notify_one(); + } + int receive() { + lock lk(monitor); + while (buffered == 0) + buffer_not_empty.wait(lk); + int i = circular_buf[begin]; + begin = (begin+1) % circular_buf.size(); + --buffered; + buffer_not_full.notify_one(); + return i; + } + +private: + int begin, end; + std::vector::size_type buffered; + std::vector circular_buf; + boost::condition_variable_any buffer_not_full, buffer_not_empty; + boost::mutex monitor; +}; + +bounded_buffer buf(2); + +boost::mutex io_mutex; + +void sender() { + int n = 0; + while (n < 1000000) { + buf.send(n); + if(!(n%10000)) + { + boost::unique_lock io_lock(io_mutex); + std::cout << "sent: " << n << std::endl; + } + ++n; + } + buf.send(-1); +} + +void receiver() { + int n; + do { + n = buf.receive(); + if(!(n%10000)) + { + boost::unique_lock io_lock(io_mutex); + std::cout << "received: " << n << std::endl; + } + } while (n != -1); // -1 indicates end of buffer + buf.send(-1); +} + +int main(int, char*[]) +{ + boost::thread thrd1(&sender); + boost::thread thrd2(&receiver); + boost::thread thrd3(&receiver); + boost::thread thrd4(&receiver); + thrd1.join(); + thrd2.join(); + thrd3.join(); + thrd4.join(); + return 0; +} diff --git a/src/boost/libs/thread/example/default_executor.cpp b/src/boost/libs/thread/example/default_executor.cpp new file mode 100644 index 000000000..ccdb38767 --- /dev/null +++ b/src/boost/libs/thread/example/default_executor.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2014 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include +#include +#include +#include +#include + +#include + + +boost::generic_executor_ref default_executor() +{ + static boost::basic_thread_pool tp(4); + return boost::generic_executor_ref(tp); +} + +void p2() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + + +void p1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + default_executor().submit(&p2); + boost::this_thread::sleep_for(boost::chrono::milliseconds(400)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +int main() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + + default_executor().submit(&p1); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + std::cout << BOOST_CONTEXTOF << std::endl; + + return 1; + +} diff --git a/src/boost/libs/thread/example/executor.cpp b/src/boost/libs/thread/example/executor.cpp new file mode 100644 index 000000000..82734347f --- /dev/null +++ b/src/boost/libs/thread/example/executor.cpp @@ -0,0 +1,207 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +boost::future p(boost::future f) { + assert(f.is_ready()); + return boost::make_ready_future(); +} + +void p1() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + //boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); +} + +void p2() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + //boost::this_thread::sleep_for(boost::chrono::seconds(10)); +} + +int f1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + std::cout << BOOST_CONTEXTOF << std::endl; + return 1; +} +int f2(int i) +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + return i + 1; +} + +void submit_some(boost::executor& tp) +{ + for (int i = 0; i < 3; ++i) { + tp.submit(&p2); + } + for (int i = 0; i < 3; ++i) { + tp.submit(&p1); + } + +} + + +void at_th_entry(boost::basic_thread_pool& ) +{ + +} + +int test_executor_adaptor() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + { + try + { + { + boost::executor_adaptor < boost::basic_thread_pool > ea(4); + std::cout << BOOST_CONTEXTOF << std::endl; + submit_some( ea); + std::cout << BOOST_CONTEXTOF << std::endl; +#if 1 + // fixme + // ERROR= tr1::bad_weak_ptr + { + boost::future t1 = boost::async(ea, &f1); + boost::future t2 = boost::async(ea, &f1); + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl; + } + std::cout << BOOST_CONTEXTOF << std::endl; + submit_some(ea); + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea3(1); + std::cout << BOOST_CONTEXTOF << std::endl; + boost::future t1 = boost::async(ea3, &f1); + std::cout << BOOST_CONTEXTOF << std::endl; + boost::future t2 = boost::async(ea3, &f1); + std::cout << BOOST_CONTEXTOF << std::endl; + //boost::future t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11 + //boost::future t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98 + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl; + } +#endif + std::cout << BOOST_CONTEXTOF << std::endl; + submit_some(ea); + std::cout << BOOST_CONTEXTOF << std::endl; + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::executor_adaptor < boost::loop_executor > ea2; + submit_some( ea2); + ea2.underlying_executor().run_queued_closures(); + } +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::executor_adaptor < boost::basic_thread_pool > ea1(4); + boost::executor_adaptor < boost::serial_executor > ea2(ea1); + submit_some(ea2); + } +#endif + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::executor_adaptor < boost::inline_executor > ea1; + submit_some(ea1); + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::executor_adaptor < boost::thread_executor > ea1; + submit_some(ea1); + } + std::cout << BOOST_CONTEXTOF << std::endl; +#if 1 + // fixme + // ERROR= tr1::bad_weak_ptr + { + boost::basic_thread_pool ea(4, at_th_entry); + boost::future t1 = boost::async(ea, &f1); + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + } +#endif + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::async(&f1); + } +#if 1 + // fixme + // ERROR= tr1::bad_weak_ptr + + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea(1); + boost::async(ea,&f1); + } +#endif + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; + } + catch (std::exception& ex) + { + std::cout << "ERROR= " << ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << " ERROR= exception thrown" << std::endl; + return 2; + } + } + // std::cout << BOOST_CONTEXTOF << std::endl; + return 0; +} + + +int main() +{ + return test_executor_adaptor(); + +#if 0 && defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \ + && defined BOOST_THREAD_PROVIDES_EXECUTORS \ + && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + + boost::basic_thread_pool executor; + // compiles + boost::make_ready_future().then(&p); + + // ?? + boost::make_ready_future().then(executor, &p); + + // doesn't compile + boost::make_ready_future().then(executor, &p); +#endif +} diff --git a/src/boost/libs/thread/example/fib_task_region.cpp b/src/boost/libs/thread/example/fib_task_region.cpp new file mode 100644 index 000000000..1540dc294 --- /dev/null +++ b/src/boost/libs/thread/example/fib_task_region.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2012 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include +#include + +#if ! defined BOOST_NO_CXX11_RANGE_BASED_FOR && ! defined BOOST_NO_CXX11_LAMBDAS + +int fib_task_region(int n) +{ + using boost::experimental::parallel::task_region; + using boost::experimental::parallel::task_region_handle; + + if (n == 0) return 0; + if (n == 1) return 1; + + int n1; + int n2; + + task_region([&](task_region_handle& trh) + { + trh.run([&] + { + n1 = fib_task_region(n - 1); + }); + + n2 = fib_task_region(n - 2); + }); + + return n1 + n2; +} + +#if defined BOOST_THREAD_PROVIDES_EXECUTORS +template +int fib_task_region_gen( Ex& ex, int n) +{ + using boost::experimental::parallel::task_region; + using boost::experimental::parallel::task_region_handle_gen; + + if (n == 0) return 0; + if (n == 1) return 1; + + int n1; + int n2; + + task_region(ex, [&](task_region_handle_gen& trh) + { + trh.run([&] + { + n1 = fib_task_region(n - 1); + }); + + n2 = fib_task_region(n - 2); + }); + + return n1 + n2; +} +#endif + +int main() +{ + for (int i = 0; i<10; ++i) { + std::cout << fib_task_region(i) << " "; + } + std::cout << std::endl; + +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + boost::basic_thread_pool tp; + for (int i = 0; i<10; ++i) { + std::cout << fib_task_region_gen(tp,i) << " "; + } + std::cout << std::endl; +#endif + return 0; +} +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/future_fallback_to.cpp b/src/boost/libs/thread/example/future_fallback_to.cpp new file mode 100644 index 000000000..7e928eec5 --- /dev/null +++ b/src/boost/libs/thread/example/future_fallback_to.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include +#include + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1_ex() +{ + BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG; + throw std::logic_error("kk"); +} + +int p1() +{ + BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG; + return 1;; +} + +int main() +{ + const int number_of_tests = 200; + BOOST_THREAD_LOG << " f1 = boost::async(boost::launch::async, &p1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + f1.wait(); + BOOST_ASSERT(f1.get()==1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "< f1 = boost::async(&p1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future f2 = f1.fallback_to(-1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + f2.wait(); + //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl; + BOOST_ASSERT(f2.get()==1); + //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl; + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "< f1 = boost::async(boost::launch::async, &p1_ex); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + f1.wait(); + BOOST_ASSERT(f1.get_or(-1)==-1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "< f1 = boost::async(boost::launch::async, &p1_ex); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future f2 = f1.fallback_to(-1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + f2.wait(); + //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl; + BOOST_ASSERT(f2.get()==-1); + //std::cout << __FILE__ << "["<< __LINE__<<"] " << std::endl; + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << "ERRORRRRR "<" << BOOST_THREAD_END_LOG; + return 0; +} +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/future_then.cpp b/src/boost/libs/thread/example/future_then.cpp new file mode 100644 index 000000000..17ef36714 --- /dev/null +++ b/src/boost/libs/thread/example/future_then.cpp @@ -0,0 +1,137 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG; + return 123; +} + +int p2(boost::future f) +{ + BOOST_THREAD_LOG << "P2<" << BOOST_THREAD_END_LOG; + try + { + return 2 * f.get(); + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<" << BOOST_THREAD_END_LOG; + return 0; +} +int p2s(boost::shared_future f) +{ + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + return 0; +} + +int main() +{ + const int number_of_tests = 100; + BOOST_THREAD_LOG << " f1 = boost::async(&p1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future f2 = f1.then(&p2); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + (void)f2.get(); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "< f1 = boost::async(&p1).share(); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future f2 = f1.then(&p2s); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + (void)f2.get(); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<" << BOOST_THREAD_END_LOG; + return 0; +} +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/future_unwrap.cpp b/src/boost/libs/thread/example/future_unwrap.cpp new file mode 100644 index 000000000..aeed9db9a --- /dev/null +++ b/src/boost/libs/thread/example/future_unwrap.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include + +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG << "P1" << BOOST_THREAD_END_LOG; + return 123; +} + +boost::future p2() +{ + BOOST_THREAD_LOG << " f1 = boost::async(boost::launch::async, &p1); + BOOST_THREAD_LOG << "P2>" << BOOST_THREAD_END_LOG; + return boost::move(f1); +} + +int main() +{ + const int number_of_tests = 100; + BOOST_THREAD_LOG << " inner_future = boost::async(boost::launch::async, &p2).unwrap(); + inner_future.wait(); + int ii = inner_future.get(); + BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG; + } +#endif + { + boost::future > outer_future = boost::async(boost::launch::async, &p2); + boost::future inner_future = outer_future.unwrap(); + inner_future.wait(); + int ii = inner_future.get(); + BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG; + } + { + boost::future > outer_future = boost::async(boost::launch::async, &p2); + boost::future inner_future = outer_future.unwrap(); + int ii = inner_future.get(); + BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG; + } + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<" << BOOST_THREAD_END_LOG; + return 0; +} +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/future_when_all.cpp b/src/boost/libs/thread/example/future_when_all.cpp new file mode 100644 index 000000000..52a40e9c0 --- /dev/null +++ b/src/boost/libs/thread/example/future_when_all.cpp @@ -0,0 +1,330 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + BOOST_THREAD_LOG + << "P1" << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + return 123; +} +int p1b() +{ + BOOST_THREAD_LOG + << "P1b" << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + return 321; +} + +int p2(boost::future f) +{ + BOOST_THREAD_LOG + << " P2 " << BOOST_THREAD_END_LOG; + try + { + return 2 * f.get(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG + << "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_ASSERT(false); + } + catch (...) + { + BOOST_THREAD_LOG + << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_ASSERT(false); + } + BOOST_THREAD_LOG + << "P2>" << BOOST_THREAD_END_LOG; + return 0; + +} +int p2s(boost::shared_future f) +{ + BOOST_THREAD_LOG + << "" << BOOST_THREAD_END_LOG; + return 0; +} + +int main() +{ + BOOST_THREAD_LOG + << " > all0 = boost::when_all(); + BOOST_THREAD_LOG + << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future > > all = boost::when_all(boost::move(f1)); + boost::csbl::tuple > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::deferred, &p1); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future > > all = boost::when_all(boost::move(f1)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::tuple > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#endif + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::make_ready_future(1); + boost::future > > all = boost::when_all(boost::move(f1)); + boost::csbl::tuple > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future f2 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_all(boost::move(f1), boost::move(f2)); + //(void) all.wait(); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future f2 = boost::make_ready_future(std::string("nnnnnnn"));; + boost::future, boost::future > > all = boost::when_all(boost::move(f1), boost::move(f2)); + //(void) all.wait(); + boost::csbl::tuple, boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector > v; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + v.push_back(boost::async(boost::launch::async, &p1)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + v.push_back(boost::async(boost::launch::async, &p1b)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future > > all = boost::when_all(v.begin(), v.end()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector > res = all.get(); + BOOST_THREAD_LOG + << res[0].get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << res[1].get() <<" " << BOOST_THREAD_END_LOG; + } + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG + << "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + BOOST_THREAD_LOG + << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + { + try + { + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future > all0 = boost::when_any(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future > > all = boost::when_any(boost::move(f1)); + boost::csbl::tuple > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::deferred, &p1); + boost::future > > all = boost::when_any(boost::move(f1)); + boost::csbl::tuple > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#endif + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future f2 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::make_ready_future(1); + boost::future f2 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::make_ready_future(std::string("aaaa")); + boost::future f2 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f2 = boost::make_ready_future(1); + boost::future f1 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::deferred, &p1); + boost::future f2 = boost::async(boost::launch::async, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future f1 = boost::async(boost::launch::async, &p1); + boost::future f2 = boost::async(boost::launch::deferred, &p1b); + boost::future,boost::future > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple,boost::future > res = all.get(); + BOOST_THREAD_LOG + << boost::csbl::get<0>(res).get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << boost::csbl::get<1>(res).get() <<" " << BOOST_THREAD_END_LOG; + } +#endif + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector > v; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + v.push_back(boost::async(boost::launch::async, &p1)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + v.push_back(boost::async(boost::launch::async, &p1b)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future > > all = boost::when_any(v.begin(), v.end()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector > res = all.get(); + BOOST_THREAD_LOG + << res[0].get() <<" " << BOOST_THREAD_END_LOG; + BOOST_THREAD_LOG + << res[1].get() <<" " << BOOST_THREAD_END_LOG; + } + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG + << "ERRORRRRR " << ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + BOOST_THREAD_LOG + << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + BOOST_THREAD_LOG + << "MAIN>" << BOOST_THREAD_END_LOG; + return 0; +} +#else +#include +using namespace boost; + +void f( boost::csbl::vector > &//vec + , BOOST_THREAD_RV_REF(future) //f + ) { +} +int main() +{ + boost::csbl::vector > vec; + f(vec, make_ready_future(0)); + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/generic_executor_ref.cpp b/src/boost/libs/thread/example/generic_executor_ref.cpp new file mode 100644 index 000000000..9e61d5dc7 --- /dev/null +++ b/src/boost/libs/thread/example/generic_executor_ref.cpp @@ -0,0 +1,163 @@ +// Copyright (C) 2014 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void p1() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + //boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); +} + +void p2() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + //boost::this_thread::sleep_for(boost::chrono::seconds(10)); +} + +int f1() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + return 1; +} +int f2(int i) +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + return i + 1; +} + +void submit_some(boost::generic_executor_ref tp) +{ + for (int i = 0; i < 3; ++i) { + tp.submit(&p2); + } + for (int i = 0; i < 3; ++i) { + tp.submit(&p1); + } + +} + +void at_th_entry(boost::basic_thread_pool& ) +{ + +} + + + +int test_generic_executor_ref() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + { + try + { + { + boost::basic_thread_pool ea(4); + submit_some( ea); + { + boost::future t1 = boost::async(ea, &f1); + boost::future t2 = boost::async(ea, &f1); + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl; + } + submit_some(ea); + { + boost::basic_thread_pool ea3(1); + boost::future t1 = boost::async(ea3, &f1); + boost::future t2 = boost::async(ea3, &f1); + //boost::future t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11 + //boost::future t2 = boost::async(ea3, boost::bind(f2, 1)); // todo this doesn't compiles yet on C++98 + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + std::cout << BOOST_CONTEXTOF << " t2= " << t2.get() << std::endl; + } + submit_some(ea); + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::loop_executor ea2; + submit_some( ea2); + ea2.run_queued_closures(); + } +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea1(4); + boost::serial_executor ea2(ea1); + submit_some(ea2); + } +#endif + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::inline_executor ea1; + submit_some(ea1); + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + //boost::thread_executor ea1; + //submit_some(ea1); + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea(4, at_th_entry); + boost::future t1 = boost::async(ea, &f1); + std::cout << BOOST_CONTEXTOF << " t1= " << t1.get() << std::endl; + } + std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea(4, at_th_entry); + boost::async(ea, &f1); + std::cout << BOOST_CONTEXTOF << std::endl; + } + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; + + } + catch (std::exception& ex) + { + std::cout << "ERROR= " << ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << " ERROR= exception thrown" << std::endl; + return 2; + } + } + // std::cout << BOOST_CONTEXTOF << std::endl; + return 0; +} + + +int main() +{ + return test_generic_executor_ref(); + + +} diff --git a/src/boost/libs/thread/example/lambda_future.cpp b/src/boost/libs/thread/example/lambda_future.cpp new file mode 100644 index 000000000..a5fec8a1b --- /dev/null +++ b/src/boost/libs/thread/example/lambda_future.cpp @@ -0,0 +1,80 @@ +// Copyright (C) 2013 Vicente Botet +// +// 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) + + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \ + && ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1800) // works since msvc-12.0 + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int main() +{ + const int number_of_tests = 100; + BOOST_THREAD_LOG << " f1 = boost::async(boost::launch::async, []() {return 123;}); + int result = f1.get(); + BOOST_THREAD_LOG << "f1 " << result << BOOST_THREAD_END_LOG; + } + { + boost::future f1 = boost::async(boost::launch::async, []() {return 123;}); + boost::future f2 = f1.then([](boost::future f) {return 2*f.get(); }); + int result = f2.get(); + BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG; + } +#if ! defined BOOST_NO_CXX14_GENERIC_LAMBDAS + { + boost::future f1 = boost::async(boost::launch::async, []() {return 123;}); + boost::future f2 = f1.then([](auto f) {return 2*f.get(); }); + int result = f2.get(); + BOOST_THREAD_LOG << "f2 " << result << BOOST_THREAD_END_LOG; + } +#endif + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<" << BOOST_THREAD_END_LOG; + return 0; +} +#else + +//#warning "This test is not supported in this configuration, either because Bosst.Thread has been configured to don't support continuations, the compiler doesn't provides lambdas or because they are buggy as for MSV versions < msvc-12.0" + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/make_future.cpp b/src/boost/libs/thread/example/make_future.cpp new file mode 100644 index 000000000..76207d7ad --- /dev/null +++ b/src/boost/libs/thread/example/make_future.cpp @@ -0,0 +1,154 @@ +// Copyright (C) 2012 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include +#include + +namespace boost +{ + + template + exception_ptr make_exception_ptr(T v) + { + return copy_exception(v); + } +} + +int p1() { return 5; } +int& p1r() { static int i=0; return i; } + +void p() { } + +#if defined BOOST_THREAD_USES_MOVE +boost::future void_compute() +{ + return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future()); +} +#endif + +boost::future compute(int x) +{ + if (x == 0) return boost::make_ready_future(0); +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + if (x < 0) return boost::make_exceptional_future(std::logic_error("Error")); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + //boost::future f1 = boost::async([]() { return x+1; }); + boost::future f1 = boost::async(p1); + return boost::move(f1); +} + +boost::future compute_ref(int x) +{ + static int i = 0; + //if (x == 0) return boost::make_ready_future(i); //This must not compile as the type is deduced as boost::future + if (x == 0) return boost::make_ready_no_decay_future(i); +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + if (x < 0) return boost::make_exceptional_future(std::logic_error("Error")); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + boost::future f1 = boost::async(p1r); + return boost::move(f1); +} + +boost::shared_future shared_compute(int x) +{ + if (x == 0) return boost::make_ready_future(0).share(); +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + if (x < 0) return boost::make_exceptional_future(std::logic_error("Error")).share(); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + //boost::future f1 = boost::async([]() { return x+1; }); + boost::shared_future f1 = boost::async(&p1).share(); + return f1; +} + + +int main() +{ + const int number_of_tests = 100; + for (int i=0; i< number_of_tests; i++) + try + { +// { +// std::cout << __FILE__ << " "<<__LINE__ << std::endl; +// boost::future f = boost::async(boost::launch::async, p1); +// std::cout << i << " "< f = void_compute(); + f.get(); + } +#endif + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future f = compute(-1); + f.wait(); + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future f = compute(0); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future f = compute_ref(0); + std::cout << f.get() << std::endl; + } +#if __cplusplus > 201103L + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + int i = 0; + boost::future f = boost::make_ready_future(std::ref(i)); + std::cout << f.get() << std::endl; + } +#endif + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + int i = 0; + boost::future f = boost::make_ready_future(boost::ref(i)); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + const int i = 0; + boost::future f = boost::make_ready_future(boost::cref(i)); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future f = compute(2); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::shared_future f = shared_compute(0); + std::cout << f.get() << std::endl; + } + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "< +#include +#include +#include +#include +#include + +namespace { +const int ITERS = 100; +boost::mutex io_mutex; +} // namespace + +template +class buffer_t +{ +public: + typedef boost::unique_lock scoped_lock; + + buffer_t(int n) + : p(0), c(0), full(0), buf(n) + { + } + + void send(int m) + { + scoped_lock lk(mutex); + while (full == buf.size()) + cond.wait(lk); + buf[p] = m; + p = (p+1) % buf.size(); + ++full; + cond.notify_one(); + } + int receive() + { + scoped_lock lk(mutex); + while (full == 0) + cond.wait(lk); + int i = buf[c]; + c = (c+1) % buf.size(); + --full; + cond.notify_one(); + return i; + } + + static buffer_t& get_buffer() + { + static buffer_t buf(2); + return buf; + } + + static void do_sender_thread() + { + for (int n = 0; n < ITERS; ++n) + { + { + boost::unique_lock lock(io_mutex); + std::cout << "sending: " << n << std::endl; + } + get_buffer().send(n); + } + } + + static void do_receiver_thread() + { + for (int x=0; x < (ITERS/2); ++x) + { + int n = get_buffer().receive(); + { + boost::unique_lock lock(io_mutex); + std::cout << "received: " << n << std::endl; + } + } + } + +private: + M mutex; + boost::condition_variable_any cond; + unsigned int p, c, full; + std::vector buf; +}; + +template +void do_test(M* dummy=0) +{ + (void)dummy; + typedef buffer_t buffer_type; + buffer_type::get_buffer(); + boost::thread thrd1(&buffer_type::do_receiver_thread); + boost::thread thrd2(&buffer_type::do_receiver_thread); + boost::thread thrd3(&buffer_type::do_sender_thread); + thrd1.join(); + thrd2.join(); + thrd3.join(); +} + +void test_buffer() +{ + do_test(); + do_test(); +} + +int main() +{ + test_buffer(); + return 0; +} diff --git a/src/boost/libs/thread/example/mutex.cpp b/src/boost/libs/thread/example/mutex.cpp new file mode 100644 index 000000000..9e4762083 --- /dev/null +++ b/src/boost/libs/thread/example/mutex.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#include +#include +#include + +boost::mutex io_mutex; // The iostreams are not guaranteed to be thread-safe! + +class counter +{ +public: + counter() : count(0) { } + + int increment() { + boost::unique_lock scoped_lock(mutex); + return ++count; + } + +private: + boost::mutex mutex; + int count; +}; + +counter c; + +void change_count() +{ + int i = c.increment(); + boost::unique_lock scoped_lock(io_mutex); + std::cout << "count == " << i << std::endl; +} + +int main(int, char*[]) +{ + const int num_threads = 4; + boost::thread_group thrds; + for (int i=0; i < num_threads; ++i) + thrds.create_thread(&change_count); + + thrds.join_all(); + + return 0; +} diff --git a/src/boost/libs/thread/example/not_interleaved.cpp b/src/boost/libs/thread/example/not_interleaved.cpp new file mode 100644 index 000000000..ad90fd1f5 --- /dev/null +++ b/src/boost/libs/thread/example/not_interleaved.cpp @@ -0,0 +1,63 @@ +// (C) Copyright 2012 Howard Hinnant +// (C) Copyright 2012 Vicente Botet +// +// 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) + +// adapted from the example given by Howard Hinnant in + +#define BOOST_THREAD_VERSION 4 + +#include +#include +#include + +void use_cerr(boost::externally_locked_stream &mcerr) +{ + using namespace boost; + chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(10); + while (chrono::steady_clock::now() < tf) + { + mcerr << "logging data to cerr\n"; + this_thread::sleep_for(chrono::milliseconds(500)); + } +} + +void use_cout(boost::externally_locked_stream &mcout) +{ + using namespace boost; + chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5); + while (chrono::steady_clock::now() < tf) + { + mcout << "logging data to cout\n"; + this_thread::sleep_for(chrono::milliseconds(250)); + } +} + +int main() +{ + using namespace boost; + + recursive_mutex terminal_mutex; + + externally_locked_stream mcerr(std::cerr, terminal_mutex); + externally_locked_stream mcout(std::cout, terminal_mutex); + externally_locked_stream mcin(std::cin, terminal_mutex); + + scoped_thread<> t1(boost::thread(use_cerr, boost::ref(mcerr))); + scoped_thread<> t2(boost::thread(use_cout, boost::ref(mcout))); + this_thread::sleep_for(chrono::seconds(2)); + std::string nm; + { + strict_lock lk(terminal_mutex); + std::ostream & gcout = mcout.get(lk); + //std::istream & gcin = mcin.get(lk); + gcout << "Enter name: "; + //gcin >> nm; + } + t1.join(); + t2.join(); + mcout << nm << '\n'; + return 0; +} + diff --git a/src/boost/libs/thread/example/not_interleaved2.cpp b/src/boost/libs/thread/example/not_interleaved2.cpp new file mode 100644 index 000000000..e3c4cddc3 --- /dev/null +++ b/src/boost/libs/thread/example/not_interleaved2.cpp @@ -0,0 +1,61 @@ +// (C) Copyright 2012 Howard Hinnant +// (C) Copyright 2012 Vicente Botet +// +// 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) + +// adapted from the example given by Howard Hinnant in + +#define BOOST_THREAD_VERSION 4 + +#include +#include +#include + +void use_cerr() +{ + using namespace boost; + chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5); + int i = 0; + while (chrono::steady_clock::now() < tf) + { + ostream_buffer mcerr(std::cerr); + mcerr.stream() << "logging data to cerr " << i++ << "\n"; + this_thread::sleep_for(chrono::milliseconds(250)); + } +} + +void use_cout() +{ + using namespace boost; + chrono::steady_clock::time_point tf = chrono::steady_clock::now() + chrono::seconds(5); + int i = 0; + while (chrono::steady_clock::now() < tf) + { + ostream_buffer mcout(std::cout); + mcout.stream() << "logging data to cout " << i++ << "\n"; + this_thread::sleep_for(chrono::milliseconds(500)); + } +} + +int main() +{ + using namespace boost; + + scoped_thread<> t1(&use_cerr); + scoped_thread<> t2(&use_cout); + this_thread::sleep_for(chrono::seconds(2)); + std::string nm = "he, he\n"; + { + ostream_buffer mcout(std::cout); + mcout.stream() << "Enter name: \n"; + } + t1.join(); + t2.join(); + { + ostream_buffer mcout(std::cout); + mcout.stream() << nm; + } + return 0; +} + diff --git a/src/boost/libs/thread/example/once.cpp b/src/boost/libs/thread/example/once.cpp new file mode 100644 index 000000000..c063a9ce4 --- /dev/null +++ b/src/boost/libs/thread/example/once.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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_PROVIDES_ONCE_CXX11 + +#include +#include +#include + +int value=0; +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +static boost::once_flag once; +//static boost::once_flag once2 = BOOST_ONCE_INIT; +#else +static boost::once_flag once = BOOST_ONCE_INIT; +//static boost::once_flag once2 = once; +#endif + +void init() +{ + ++value; +} + +void thread_proc() +{ + boost::call_once(&init, once); +} + +int main() +{ + boost::thread_group threads; + for (int i=0; i<5; ++i) + threads.create_thread(&thread_proc); + threads.join_all(); + assert(value == 1); +} diff --git a/src/boost/libs/thread/example/parallel_accumulate.cpp b/src/boost/libs/thread/example/parallel_accumulate.cpp new file mode 100644 index 000000000..acd72017e --- /dev/null +++ b/src/boost/libs/thread/example/parallel_accumulate.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 2014 Vicente Botet +// +// 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) + +#include + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +template +struct accumulate_block +{ + //typedef T result_type; + T operator()(Iterator first,Iterator last) + { + return std::accumulate(first,last,T()); + } +}; + +template +T parallel_accumulate(Iterator first,Iterator last,T init) +{ + unsigned long const length=static_cast(std::distance(first,last)); + + if(!length) + return init; + + unsigned long const block_size=25; + unsigned long const num_blocks=(length+block_size-1)/block_size; + + boost::csbl::vector > futures(num_blocks-1); + boost::basic_thread_pool pool; + + Iterator block_start=first; + for(unsigned long i=0;i<(num_blocks-1);++i) + { + Iterator block_end=block_start; + std::advance(block_end,block_size); + futures[i]=boost::async(pool, accumulate_block(), block_start, block_end); + block_start=block_end; + } + T last_result=accumulate_block()(block_start,last); + T result=init; + for(unsigned long i=0;i<(num_blocks-1);++i) + { + result+=futures[i].get(); + } + result += last_result; + return result; +} + + +int main() +{ + try + { + const int s = 1001; + std::vector vec; + vec.reserve(s); + for (int i=0; i + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include +#include +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +#include +#include +#include +#include +#include + +template +struct sorter +{ + boost::basic_thread_pool pool; + typedef std::list return_type; + + std::list do_sort(std::list chunk_data) + { + if(chunk_data.empty()) + { + return chunk_data; + } + + std::list result; + result.splice(result.begin(),chunk_data, chunk_data.begin()); + T const& partition_val=*result.begin(); + + typename std::list::iterator divide_point= + std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val){return val new_lower_chunk; + new_lower_chunk.splice(new_lower_chunk.end(), chunk_data, chunk_data.begin(), divide_point); + + boost::future > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk)); + //boost::future > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk)); + + std::list new_higher(do_sort(chunk_data)); + + result.splice(result.end(),new_higher); + while(!new_lower.is_ready()) + { + pool.schedule_one_or_yield(); + } + + result.splice(result.begin(),new_lower.get()); + return result; + } +}; + + +template +std::list parallel_quick_sort(std::list& input) +{ + if(input.empty()) + { + return input; + } + sorter s; + + return s.do_sort(input); +} + + +int main() +{ + try + { + const int s = 101; + std::list lst; + for (int i=0; i r = parallel_quick_sort(lst); + for (std::list::const_iterator it=r.begin(); it != r.end(); ++it) + std::cout << *it << std::endl; + + } + catch (std::exception& ex) + { + std::cout << "ERROR= " << ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << " ERROR= exception thrown" << std::endl; + return 2; + } + return 0; +} +#else +//#warning "This compiler doesn't supports variadics and move semantics" +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/perf_condition_variable.cpp b/src/boost/libs/thread/example/perf_condition_variable.cpp new file mode 100644 index 000000000..058386125 --- /dev/null +++ b/src/boost/libs/thread/example/perf_condition_variable.cpp @@ -0,0 +1,237 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// 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) +// +// This performance test is based on the performance test provided by maxim.yegorushkin +// at https://svn.boost.org/trac/boost/ticket/7422 + +#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////// + +namespace +{ + //////////////////////////////////////////////////////////////////////////////////////////////// + +// class Stopwatch +// { +// public: +// typedef long long rep; +// +// static rep now() +// { +// timespec ts; +// if (clock_gettime(CLOCK_MONOTONIC, &ts)) abort(); +// return ts.tv_sec * rep(1000000000) + ts.tv_nsec; +// } +// +// Stopwatch() : +// start_(now()) +// { +// } +// +// rep elapsed() const +// { +// return now() - start_; +// } +// +// private: +// rep start_; +// }; + + typedef boost::chrono::simple_stopwatch<> Stopwatch; + //////////////////////////////////////////////////////////////////////////////////////////////// + + struct BoostTypes + { + typedef boost::condition_variable condition_variable; + typedef boost::mutex mutex; + typedef boost::mutex::scoped_lock scoped_lock; + }; + + struct StdTypes + { + typedef std::condition_variable condition_variable; + typedef std::mutex mutex; + typedef std::unique_lock scoped_lock; + }; + + template + struct SharedData: Types + { + unsigned const iterations; + unsigned counter; + unsigned semaphore; + typename Types::condition_variable cnd; + typename Types::mutex mtx; + Stopwatch::rep producer_time; + + SharedData(unsigned iterations, unsigned consumers) : + iterations(iterations), counter(), semaphore(consumers) // Initialize to the number of consumers. (*) + , producer_time() + { + } + }; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + + template + void producer_thread(S* shared_data) + { + Stopwatch sw; + + unsigned const consumers = shared_data->semaphore; // (*) + for (unsigned i = shared_data->iterations; i--;) + { + { + typename S::scoped_lock lock(shared_data->mtx); + // Wait till all consumers signal. + while (consumers != shared_data->semaphore) + { + shared_data->cnd.wait(lock); + } + shared_data->semaphore = 0; + // Signal consumers. + ++shared_data->counter; + } + shared_data->cnd.notify_all(); + } + + shared_data->producer_time = sw.elapsed().count(); + } + + template + void consumer_thread(S* shared_data) + { + unsigned counter = 0; + while (counter != shared_data->iterations) + { + { + typename S::scoped_lock lock(shared_data->mtx); + // Wait till the producer signals. + while (counter == shared_data->counter) + { + shared_data->cnd.wait(lock); + } + counter = shared_data->counter; + // Signal the producer. + ++shared_data->semaphore; + } + shared_data->cnd.notify_all(); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + + template + Stopwatch::rep benchmark_ping_pong(unsigned consumer_count) + { + typedef SharedData S; + + auto best_producer_time = std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + + std::vector consumers + { consumer_count }; + + // Run the benchmark 10 times and report the best time. + for (int times = 10; times--;) + { + S shared_data + { 100000, consumer_count }; + + // Start the consumers. + for (unsigned i = 0; i < consumer_count; ++i) + consumers[i] = std::thread + { consumer_thread , &shared_data }; + // Start the producer and wait till it finishes. + std::thread + { producer_thread , &shared_data }.join(); + // Wait till consumers finish. + for (unsigned i = 0; i < consumer_count; ++i) + consumers[i].join(); + + best_producer_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_producer_time, shared_data.producer_time); + + } + + return best_producer_time; + } + +//////////////////////////////////////////////////////////////////////////////////////////////// + +} // namespace + +//////////////////////////////////////////////////////////////////////////////////////////////// + +// sudo chrt -f 99 /usr/bin/time -f "\n***\ntime: %E\ncontext switches: %c\nwaits: %w" /home/max/otsquant/build/Linux-x86_64-64.g++-release/test/test + +/* + + Producer-consumer ping-pong tests. It aims to benchmark condition variables with and without + thread cancellation support by comparing the time it took to complete the benchmark. + + Condition variable with thread cancellation support is boost::condition_variable from + boost-1.51. Without - std::condition_variable that comes with gcc-4.7.2. + + One producer, one to CONSUMER_MAX consumers. The benchmark calls + condition_variable::notify_all() without holding a mutex to maximize contention within this + function. Each benchmark for a number of consumers is run three times and the best time is + picked to get rid of outliers. + + The results are reported for each benchmark for a number of consumers. The most important number + is (std - boost) / std * 100. Positive numbers are when boost::condition_variable is faster, + negative it is slower. + + */ + +int main() +{ + std::printf("MAIN\n"); + enum + { + CONSUMER_MAX = 2 + }; + + struct + { + Stopwatch::rep boost, std; + } best_times[CONSUMER_MAX] = {}; + + for (unsigned i = 1; i <= CONSUMER_MAX; ++i) + { + auto& b = best_times[i - 1]; + std::printf("STD: %d\n", i); + b.std = benchmark_ping_pong (i); + std::printf("BOOST: %d\n", i); + b.boost = benchmark_ping_pong (i); + + std::printf("consumers: %4d\n", i); + std::printf("best std producer time: %15.9fsec\n", b.std * 1e-9); + std::printf("best boost producer time: %15.9fsec\n", b.boost * 1e-9); + std::printf("(std - boost) / std: %7.2f%%\n", (b.std - b.boost) * 100. / b.std); + } + + printf("\ncsv:\n\n"); + printf("consumers,(std-boost)/std,std,boost\n"); + for (unsigned i = 1; i <= CONSUMER_MAX; ++i) + { + auto& b = best_times[i - 1]; + printf("%d,%f,%lld,%lld\n", i, (b.std - b.boost) * 100. / b.std, b.std, b.boost); + } + return 1; +} diff --git a/src/boost/libs/thread/example/perf_shared_mutex.cpp b/src/boost/libs/thread/example/perf_shared_mutex.cpp new file mode 100644 index 000000000..b58c0079c --- /dev/null +++ b/src/boost/libs/thread/example/perf_shared_mutex.cpp @@ -0,0 +1,72 @@ +// (C) Copyright 2013 Andrey +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// 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) +// +// This performance test is based on the performance test provided by maxim.yegorushkin +// at https://svn.boost.org/trac/boost/ticket/7422 + +#define BOOST_THREAD_USES_CHRONO + +#include +#include +#include +#include + +#include + +using namespace boost; + +shared_mutex mtx; +const int cycles = 10000; + +void shared() +{ + int cycle(0); + while (++cycle < cycles) + { + shared_lock lock(mtx); + } +} + +void unique() +{ + int cycle(0); + while (++cycle < cycles) + { + unique_lock lock(mtx); + } +} + +int main() +{ + boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION ()); + for (int i =100; i>0; --i) { + boost::chrono::high_resolution_clock clock; + boost::chrono::high_resolution_clock::time_point s1 = clock.now(); + thread t0(shared); + thread t1(shared); + thread t2(unique); + //thread t11(shared); + //thread t12(shared); + //thread t13(shared); + + t0.join(); + t1.join(); + t2.join(); + //t11.join(); +// t12.join(); + // t13.join(); + boost::chrono::high_resolution_clock::time_point f1 = clock.now(); + //std::cout << " Time spent:" << (f1 - s1) << std::endl; + best_time = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (best_time, f1 - s1); + + } + std::cout << "Best Time spent:" << best_time << std::endl; + std::cout << "Time spent/cycle:" << best_time/cycles/3 << std::endl; + + return 1; +} + diff --git a/src/boost/libs/thread/example/producer_consumer.cpp b/src/boost/libs/thread/example/producer_consumer.cpp new file mode 100644 index 000000000..73ad04fb7 --- /dev/null +++ b/src/boost/libs/thread/example/producer_consumer.cpp @@ -0,0 +1,147 @@ +// (C) Copyright 2012 Howard Hinnant +// (C) Copyright 2012 Vicente Botet +// +// 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) + +// adapted from the example given by Howard Hinnant in + +#include + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include +#include +#ifdef XXXX +#include + typedef boost::externally_locked_stream the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif +#include + +void producer(the_ostream & /*mos*/, boost::sync_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + sbq.push(i); + //sbq << i; + //mos << "push(" << i << ") "<< sbq.size()<<"\n"; + this_thread::sleep_for(chrono::milliseconds(200)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} + +void consumer( + the_ostream & /*mos*/, + boost::sync_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + sbq.pull(r); + //sbq >> r; + //mos << i << " pull(" << r << ") "<< sbq.size()<<"\n"; + + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +void consumer2(the_ostream &/*mos*/, boost::sync_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + queue_op_status st = sbq.try_pull(r); + if (queue_op_status::closed == st) break; + if (queue_op_status::success == st) { + //mos << i << " pull(" << r << ")\n"; + } + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +void consumer3(the_ostream &/*mos*/, boost::sync_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + queue_op_status res = sbq.wait_pull(r); + if (res==queue_op_status::closed) break; + //mos << i << " wait_pull(" << r << ")\n"; + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(...) + { + //mos << "exception !!!\n"; + } +} + +int main() +{ + using namespace boost; + +#ifdef XXXX + recursive_mutex terminal_mutex; + + externally_locked_stream mcerr(std::cerr, terminal_mutex); + externally_locked_stream mcout(std::cout, terminal_mutex); + externally_locked_stream mcin(std::cin, terminal_mutex); +#else + the_ostream &mcerr = std::cout; + the_ostream &mcout = std::cerr; + //the_istream &mcin = std::cin; +#endif + + sync_queue sbq; + + { + mcout << "begin of main" << std::endl; + scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq))); + scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq))); + scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq))); + + this_thread::sleep_for(chrono::seconds(1)); + + mcout << "closed()" << std::endl; + sbq.close(); + mcout << "closed()" << std::endl; + + } // all threads joined here. + mcout << "end of main" << std::endl; + return 0; +} + diff --git a/src/boost/libs/thread/example/producer_consumer2.cpp b/src/boost/libs/thread/example/producer_consumer2.cpp new file mode 100644 index 000000000..a8264a9bb --- /dev/null +++ b/src/boost/libs/thread/example/producer_consumer2.cpp @@ -0,0 +1,150 @@ +// (C) Copyright 2014 Vicente Botet +// +// 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) + +// adapted from the example given by Howard Hinnant in + +#include + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include +#include +#ifdef XXXX +#include + typedef boost::externally_locked_stream the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif +#include +#include +#include +#include +#include + +void producer(the_ostream &/*mos*/, boost::queue_back sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + sbq.push(i); + //sbq << i; + //mos << "push(" << i << ") " << sbq.size() <<"\n"; + this_thread::sleep_for(chrono::milliseconds(200)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} + +void consumer( + the_ostream &/*mos*/, + boost::queue_front sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + sbq.pull(r); + //sbq >> r; + //mos << i << " pull(" << r << ") " << sbq.size() <<"\n"; + + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +void consumer2(the_ostream &/*mos*/, boost::queue_front sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + queue_op_status st = sbq.try_pull(r); + if (queue_op_status::closed == st) break; + if (queue_op_status::success == st) { + //mos << i << " try_pull(" << r << ")\n"; + } + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +void consumer3(the_ostream &/*mos*/, boost::queue_front sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + queue_op_status res = sbq.wait_pull(r); + if (res==queue_op_status::closed) break; + //mos << i << " wait_pull(" << r << ")\n"; + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(...) + { + //mos << "exception !!!\n"; + } +} + +int main() +{ + using namespace boost; + +#ifdef XXXX + recursive_mutex terminal_mutex; + + externally_locked_stream mcerr(std::cerr, terminal_mutex); + externally_locked_stream mcout(std::cout, terminal_mutex); + externally_locked_stream mcin(std::cin, terminal_mutex); +#else + the_ostream &mcerr = std::cout; + the_ostream &mcout = std::cerr; + //the_istream &mcin = std::cin; +#endif + + queue_adaptor > sbq; + + { + mcout << "begin of main" << std::endl; + scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back(sbq))); + scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back(sbq))); + scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front(sbq))); + + this_thread::sleep_for(chrono::seconds(1)); + + mcout << "closed()" << std::endl; + sbq.close(); + mcout << "closed()" << std::endl; + + } // all threads joined here. + mcout << "end of main" << std::endl; + return 0; +} + diff --git a/src/boost/libs/thread/example/producer_consumer_bounded.cpp b/src/boost/libs/thread/example/producer_consumer_bounded.cpp new file mode 100644 index 000000000..70158a3e9 --- /dev/null +++ b/src/boost/libs/thread/example/producer_consumer_bounded.cpp @@ -0,0 +1,146 @@ +// (C) Copyright 2012 Howard Hinnant +// (C) Copyright 2012 Vicente Botet +// +// 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) + +// adapted from the example given by Howard Hinnant in + +#include + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +//#define XXXX + +#include +#include +#ifdef XXXX +#include + typedef boost::externally_locked_stream the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif + +#include + +void producer(the_ostream &/*mos*/, boost::sync_bounded_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + sbq.push_back(i); + //sbq << i; + //mos << "push_back(" << i << ") "<< sbq.size()<<"\n"; + this_thread::sleep_for(chrono::milliseconds(200)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} + +void consumer(the_ostream &/*mos*/, boost::sync_bounded_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + sbq.pull_front(r); + //sbq >> r; + //mos << i << " pull_front(" << r << ") "<< sbq.size()<<"\n"; + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(sync_queue_is_closed&) + { + //mos << "closed !!!\n"; + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +void consumer2(the_ostream &/*mos*/, boost::sync_bounded_queue & sbq) +{ + using namespace boost; + try { + for(int i=0; ;++i) + { + int r; + queue_op_status st = sbq.try_pull_front(r); + if (queue_op_status::closed == st) break; + if (queue_op_status::success == st) { + //mos << i << " pull(" << r << ")\n"; + } + this_thread::sleep_for(chrono::milliseconds(250)); + } + } + catch(...) + { + //mos << "exception !!!\n"; + } +} +//void consumer3(the_ostream &mos, boost::sync_bounded_queue & sbq) +//{ +// using namespace boost; +// bool closed=false; +// try { +// for(int i=0; ;++i) +// { +// int r; +// queue_op_status res = sbq.wait_and_pull(r); +// if (res==queue_op_status::closed) break; +// //mos << i << " wait_and_pull(" << r << ")\n"; +// this_thread::sleep_for(chrono::milliseconds(250)); +// } +// } +// catch(...) +// { +// //mos << "exception !!!\n"; +// } +//} + +int main() +{ + using namespace boost; +#ifdef XXXX + recursive_mutex terminal_mutex; + + externally_locked_stream mcerr(std::cerr, terminal_mutex); + externally_locked_stream mcout(std::cout, terminal_mutex); + externally_locked_stream mcin(std::cin, terminal_mutex); +#else + the_ostream &mcerr = std::cout; + the_ostream &mcout = std::cerr; + //the_istream &mcin = std::cin; +#endif + + sync_bounded_queue sbq(10); + + { + mcout << "begin of main" << std::endl; + scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq))); + scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), boost::ref(sbq))); + scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), boost::ref(sbq))); + + this_thread::sleep_for(chrono::seconds(1)); + + sbq.close(); + mcout << "closed()" << std::endl; + + } // all threads joined here. + mcout << "end of main" << std::endl; + return 0; +} + diff --git a/src/boost/libs/thread/example/recursive_mutex.cpp b/src/boost/libs/thread/example/recursive_mutex.cpp new file mode 100644 index 000000000..8cb99d30d --- /dev/null +++ b/src/boost/libs/thread/example/recursive_mutex.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#include +#include +#include + +class counter +{ +public: + counter() : count(0) { } + + int add(int val) { + boost::unique_lock scoped_lock(mutex); + count += val; + return count; + } + int increment() { + boost::unique_lock scoped_lock(mutex); + return add(1); + } + +private: + boost::recursive_mutex mutex; + int count; +}; + +counter c; + +void change_count() +{ + //std::cout << "count == " << c.increment() << std::endl; +} + +int main(int, char*[]) +{ + const int num_threads=4; + + boost::thread_group threads; + for (int i=0; i < num_threads; ++i) + threads.create_thread(&change_count); + + threads.join_all(); + + return 0; +} diff --git a/src/boost/libs/thread/example/scoped_thread.cpp b/src/boost/libs/thread/example/scoped_thread.cpp new file mode 100644 index 000000000..9242f5803 --- /dev/null +++ b/src/boost/libs/thread/example/scoped_thread.cpp @@ -0,0 +1,83 @@ +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente Botet +// +// 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 3 + +#include +#include + +void do_something(int& i) +{ + ++i; +} +void f(int, int) +{ +} + +struct func +{ + int& i; + + func(int& i_) : + i(i_) + { + } + + void operator()() + { + for (unsigned j = 0; j < 1000000; ++j) + { + do_something(i); + } + } +}; + +void do_something_in_current_thread() +{ +} + +int main() +{ + { + int some_local_state=0; + boost::strict_scoped_thread<> t( (boost::thread(func(some_local_state)))); + + do_something_in_current_thread(); + } + { + int some_local_state=0; + boost::thread t(( func(some_local_state) )); + boost::strict_scoped_thread<> g( (boost::move(t)) ); + + do_something_in_current_thread(); + } + { + int some_local_state=0; + boost::scoped_thread<> t( (boost::thread(func(some_local_state)))); + + if (t.joinable()) + t.join(); + else + do_something_in_current_thread(); + } +#if 0 + { + int some_local_state=0; + boost::thread t(( func(some_local_state) )); + boost::scoped_thread<> g( (boost::move(t)) ); + if (g.joinable()) + g.detach(); + + do_something_in_current_thread(); + } +#endif + { + boost::scoped_thread<> g( &f, 1, 2 ); + do_something_in_current_thread(); + } + return 0; +} + diff --git a/src/boost/libs/thread/example/serial_executor.cpp b/src/boost/libs/thread/example/serial_executor.cpp new file mode 100644 index 000000000..e3c2c340a --- /dev/null +++ b/src/boost/libs/thread/example/serial_executor.cpp @@ -0,0 +1,107 @@ +// Copyright (C) 2015 Vicente J. Botet Escriba +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void p1() +{ + //std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(30)); + //std::cout << BOOST_CONTEXTOF << std::endl; +} + +void p2() +{ + //std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); + //std::cout << BOOST_CONTEXTOF << std::endl; +} + +int f1() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + return 1; +} +int f2(int i) +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + return i + 1; +} + +void submit_some(boost::serial_executor& tp) +{ + for (int i = 0; i < 3; ++i) { + std::cout << BOOST_CONTEXTOF << std::endl; + tp.submit(&p2); + } + for (int i = 0; i < 3; ++i) { + std::cout << BOOST_CONTEXTOF << std::endl; + tp.submit(&p1); + } + +} + + +void at_th_entry(boost::basic_thread_pool& ) +{ + +} + +int test_executor_adaptor() +{ + { + try + { + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + { + boost::basic_thread_pool ea1(4); + boost::serial_executor ea2(ea1); + submit_some(ea2); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + } +#endif + } + catch (std::exception& ex) + { + std::cout << "ERROR= " << ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << " ERROR= exception thrown" << std::endl; + return 2; + } + } + return 0; +} + + +int main() +{ + return test_executor_adaptor(); +} diff --git a/src/boost/libs/thread/example/serial_executor_cont.cpp b/src/boost/libs/thread/example/serial_executor_cont.cpp new file mode 100644 index 000000000..1883b0718 --- /dev/null +++ b/src/boost/libs/thread/example/serial_executor_cont.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2015 Vicente J. Botet Escriba +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void p1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(30)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +void p2() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +int f1() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + return 1; +} +int f2(int i) +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + return i + 1; +} + +void submit_some(boost::serial_executor_cont& tp) +{ + std::cout << BOOST_CONTEXTOF << std::endl; + for (int i = 0; i < 3; ++i) { + std::cout << BOOST_CONTEXTOF << std::endl; + tp.submit(&p2); + } + for (int i = 0; i < 3; ++i) { + std::cout << BOOST_CONTEXTOF << std::endl; + tp.submit(&p1); + } + std::cout << BOOST_CONTEXTOF << std::endl; + +} + + +void at_th_entry(boost::basic_thread_pool& ) +{ + +} + +int test_executor_adaptor() +{ + // std::cout << BOOST_CONTEXTOF << std::endl; + { + try + { + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + // std::cout << BOOST_CONTEXTOF << std::endl; + { + boost::basic_thread_pool ea1(4); + boost::serial_executor_cont ea2(ea1); + submit_some(ea2); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + } +#endif + // std::cout << BOOST_CONTEXTOF << std::endl; + } + catch (std::exception& ex) + { + std::cout << "ERROR= " << ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << " ERROR= exception thrown" << std::endl; + return 2; + } + } + // std::cout << BOOST_CONTEXTOF << std::endl; + return 0; +} + + +int main() +{ + return test_executor_adaptor(); +} diff --git a/src/boost/libs/thread/example/shared_monitor.cpp b/src/boost/libs/thread/example/shared_monitor.cpp new file mode 100644 index 000000000..d1996588e --- /dev/null +++ b/src/boost/libs/thread/example/shared_monitor.cpp @@ -0,0 +1,144 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// 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) + +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_DONT_USE_CHRONO +#include +#endif +#include +#include + +#define EXCLUSIVE 1 +#define SHARED 2 + +#define MODE SHARED + +class A +{ +#if MODE == EXCLUSIVE + typedef boost::mutex mutex_type; +#elif MODE == SHARED + typedef boost::shared_mutex mutex_type; +#else +#error MODE not set +#endif + typedef std::vector C; + mutable mutex_type mut_; + C data_; +public: + A() : data_(10000000) {} + A(const A& a); + A& operator=(const A& a); + + void compute(const A& x, const A& y); +}; + +A::A(const A& a) +{ +#if MODE == EXCLUSIVE + boost::unique_lock lk(a.mut_); +#elif MODE == SHARED + boost::shared_lock lk(a.mut_); +#else +#error MODE not set +#endif + data_ = a.data_; +} + +A& +A::operator=(const A& a) +{ + if (this != &a) + { + boost::unique_lock lk1(mut_, boost::defer_lock); +#if MODE == EXCLUSIVE + boost::unique_lock lk2(a.mut_, boost::defer_lock); +#elif MODE == SHARED + boost::shared_lock lk2(a.mut_, boost::defer_lock); +#else +#error MODE not set +#endif + boost::lock(lk1, lk2); + data_ = a.data_; + } + return *this; +} + +void +A::compute(const A& x, const A& y) +{ + boost::unique_lock lk1(mut_, boost::defer_lock); +#if MODE == EXCLUSIVE + boost::unique_lock lk2(x.mut_, boost::defer_lock); + boost::unique_lock lk3(y.mut_, boost::defer_lock); +#elif MODE == SHARED + boost::shared_lock lk2(x.mut_, boost::defer_lock); + boost::shared_lock lk3(y.mut_, boost::defer_lock); +#else +#error MODE not set +#endif + boost::lock(lk1, lk2, lk3); + assert(data_.size() == x.data_.size()); + assert(data_.size() == y.data_.size()); + for (unsigned i = 0; i < data_.size(); ++i) + data_[i] = (x.data_[i] + y.data_[i]) / 2; +} + +A a1; +A a2; + +void test_s() +{ + A la3 = a1; + for (int i = 0; i < 150; ++i) + { + la3.compute(a1, a2); + } +} + +void test_w() +{ + A la3 = a1; + for (int i = 0; i < 10; ++i) + { + la3.compute(a1, a2); + a1 = la3; + a2 = la3; +#if defined BOOST_THREAD_DONT_USE_CHRONO + boost::this_thread::sleep_for(boost::chrono::seconds(1)); +#endif + } +} + +int main() +{ +#if defined BOOST_THREAD_DONT_USE_CHRONO + typedef boost::chrono::high_resolution_clock Clock; + typedef boost::chrono::duration sec; + Clock::time_point t0 = Clock::now(); +#endif + std::vector v; + boost::thread thw(test_w); + v.push_back(&thw); + boost::thread thr0(test_w); + v.push_back(&thr0); + boost::thread thr1(test_w); + v.push_back(&thr1); + boost::thread thr2(test_w); + v.push_back(&thr2); + boost::thread thr3(test_w); + v.push_back(&thr3); + for (std::size_t i = 0; i < v.size(); ++i) + v[i]->join(); +#if defined BOOST_THREAD_DONT_USE_CHRONO + Clock::time_point t1 = Clock::now(); + std::cout << sec(t1-t0) << '\n'; +#endif + return 0; +} diff --git a/src/boost/libs/thread/example/shared_mutex.cpp b/src/boost/libs/thread/example/shared_mutex.cpp new file mode 100644 index 000000000..c0ef7a522 --- /dev/null +++ b/src/boost/libs/thread/example/shared_mutex.cpp @@ -0,0 +1,746 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// 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_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include +#include +#include +#include +#include +#include + +#if defined BOOST_THREAD_USES_CHRONO +#include + + +enum {reading, writing}; +int state = reading; + +#if 1 + +boost::mutex& +cout_mut() +{ + static boost::mutex m; + return m; +} + +void +print(const char* tag, unsigned count, char ch) +{ + boost::lock_guard _(cout_mut()); + std::cout << tag << count << ch; +} + +#elif 0 + +boost::recursive_mutex& +cout_mut() +{ + static boost::recursive_mutex m; + return m; +} + +void print() {} + +template +void +print(const A0& a0, const Args& ...args) +{ + boost::lock_guard _(cout_mut()); + std::cout << a0; + print(args...); +} + +#else + +template +void +print(const A0&, const A1& a1, const A2&) +{ + assert(a1 > 10000); +} + +#endif + +namespace S +{ + +boost::shared_mutex mut; + +void reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock_shared(); + assert(state == reading); + ++count; + mut.unlock_shared(); + } + print("reader = ", count, '\n'); +} + +void writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock(); + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + print("writer = ", count, '\n'); +} + +void try_reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared()) + { + assert(state == reading); + ++count; + mut.unlock_shared(); + } + } + print("try_reader = ", count, '\n'); +} + +void try_writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock()) + { + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + } + print("try_writer = ", count, '\n'); +} + +void try_for_reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + ++count; + mut.unlock_shared(); + } + } + print("try_for_reader = ", count, '\n'); +} + +void try_for_writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_for(boost::chrono::microseconds(5))) + { + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + } + print("try_for_writer = ", count, '\n'); +} + +void +test_shared_mutex() +{ + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(reader); + boost::thread t2(writer); + boost::thread t3(reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(try_reader); + boost::thread t2(try_writer); + boost::thread t3(try_reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(try_for_reader); + boost::thread t2(try_for_writer); + boost::thread t3(try_for_reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; +} + +} + +namespace U +{ + +boost::upgrade_mutex mut; + +void reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock_shared(); + assert(state == reading); + ++count; + mut.unlock_shared(); + } + print("reader = ", count, '\n'); +} + +void writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock(); + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + print("writer = ", count, '\n'); +} + +void try_reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared()) + { + assert(state == reading); + ++count; + mut.unlock_shared(); + } + } + print("try_reader = ", count, '\n'); +} + +void try_writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock()) + { + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + } + print("try_writer = ", count, '\n'); +} + +void try_for_reader() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + ++count; + mut.unlock_shared(); + } + } + print("try_for_reader = ", count, '\n'); +} + +void try_for_writer() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_for(boost::chrono::microseconds(5))) + { + state = writing; + assert(state == writing); + state = reading; + ++count; + mut.unlock(); + } + } + print("try_for_writer = ", count, '\n'); +} + +void upgradable() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock_upgrade(); + assert(state == reading); + ++count; + mut.unlock_upgrade(); + } + print("upgradable = ", count, '\n'); +} + +void try_upgradable() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_upgrade()) + { + assert(state == reading); + ++count; + mut.unlock_upgrade(); + } + } + print("try_upgradable = ", count, '\n'); +} + +void try_for_upgradable() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_upgrade_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + ++count; + mut.unlock_upgrade(); + } + } + print("try_for_upgradable = ", count, '\n'); +} + +void clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock_shared(); + assert(state == reading); + if (mut.try_unlock_shared_and_lock()) + { + state = writing; + } + else if (mut.try_unlock_shared_and_lock_upgrade()) + { + assert(state == reading); + mut.unlock_upgrade_and_lock(); + state = writing; + } + else + { + mut.unlock_shared(); + continue; + } + assert(state == writing); + state = reading; + mut.unlock_and_lock_upgrade(); + assert(state == reading); + mut.unlock_upgrade_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + print("clockwise = ", count, '\n'); +} + +void counter_clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + mut.lock_upgrade(); + assert(state == reading); + mut.unlock_upgrade_and_lock(); + assert(state == reading); + state = writing; + assert(state == writing); + state = reading; + mut.unlock_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + print("counter_clockwise = ", count, '\n'); +} + +void try_clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared()) + { + assert(state == reading); + if (mut.try_unlock_shared_and_lock()) + { + state = writing; + } + else if (mut.try_unlock_shared_and_lock_upgrade()) + { + assert(state == reading); + mut.unlock_upgrade_and_lock(); + state = writing; + } + else + { + mut.unlock_shared(); + continue; + } + assert(state == writing); + state = reading; + mut.unlock_and_lock_upgrade(); + assert(state == reading); + mut.unlock_upgrade_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + } + print("try_clockwise = ", count, '\n'); +} + +void try_for_clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_shared_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + if (mut.try_unlock_shared_and_lock_for(boost::chrono::microseconds(5))) + { + state = writing; + } + else if (mut.try_unlock_shared_and_lock_upgrade_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + mut.unlock_upgrade_and_lock(); + state = writing; + } + else + { + mut.unlock_shared(); + continue; + } + assert(state == writing); + state = reading; + mut.unlock_and_lock_upgrade(); + assert(state == reading); + mut.unlock_upgrade_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + } + print("try_for_clockwise = ", count, '\n'); +} + +void try_counter_clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_upgrade()) + { + assert(state == reading); + if (mut.try_unlock_upgrade_and_lock()) + { + assert(state == reading); + state = writing; + assert(state == writing); + state = reading; + mut.unlock_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + else + { + mut.unlock_upgrade(); + } + } + } + print("try_counter_clockwise = ", count, '\n'); +} + +void try_for_counter_clockwise() +{ + typedef boost::chrono::steady_clock Clock; + unsigned count = 0; + Clock::time_point until = Clock::now() + boost::chrono::seconds(3); + while (Clock::now() < until) + { + if (mut.try_lock_upgrade_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + if (mut.try_unlock_upgrade_and_lock_for(boost::chrono::microseconds(5))) + { + assert(state == reading); + state = writing; + assert(state == writing); + state = reading; + mut.unlock_and_lock_shared(); + assert(state == reading); + mut.unlock_shared(); + ++count; + } + else + { + mut.unlock_upgrade(); + } + } + } + print("try_for_counter_clockwise = ", count, '\n'); +} + +void +test_upgrade_mutex() +{ + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(reader); + boost::thread t2(writer); + boost::thread t3(reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(try_reader); + boost::thread t2(try_writer); + boost::thread t3(try_reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(try_for_reader); + boost::thread t2(try_for_writer); + boost::thread t3(try_for_reader); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(reader); + boost::thread t2(writer); + boost::thread t3(upgradable); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(reader); + boost::thread t2(writer); + boost::thread t3(try_upgradable); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + boost::thread t1(reader); + boost::thread t2(writer); + boost::thread t3(try_for_upgradable); + t1.join(); + t2.join(); + t3.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + state = reading; + boost::thread t1(clockwise); + boost::thread t2(counter_clockwise); + boost::thread t3(clockwise); + boost::thread t4(counter_clockwise); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + { + state = reading; + boost::thread t1(try_clockwise); + boost::thread t2(try_counter_clockwise); + t1.join(); + t2.join(); + } + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; +// { +// state = reading; +// boost::thread t1(try_for_clockwise); +// boost::thread t2(try_for_counter_clockwise); +// t1.join(); +// t2.join(); +// } +// std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; +} + +} + +namespace Assignment +{ + +class A +{ + typedef boost::upgrade_mutex mutex_type; + typedef boost::shared_lock SharedLock; + typedef boost::upgrade_lock UpgradeLock; + typedef boost::unique_lock Lock; + + mutable mutex_type mut_; + std::vector data_; + +public: + + A(const A& a) + { + SharedLock _(a.mut_); + data_ = a.data_; + } + + A& operator=(const A& a) + { + if (this != &a) + { + Lock this_lock(mut_, boost::defer_lock); + SharedLock that_lock(a.mut_, boost::defer_lock); + boost::lock(this_lock, that_lock); + data_ = a.data_; + } + return *this; + } + + void swap(A& a) + { + Lock this_lock(mut_, boost::defer_lock); + Lock that_lock(a.mut_, boost::defer_lock); + boost::lock(this_lock, that_lock); + data_.swap(a.data_); + } + + void average(A& a) + { + assert(data_.size() == a.data_.size()); + assert(this != &a); + + Lock this_lock(mut_, boost::defer_lock); + UpgradeLock share_that_lock(a.mut_, boost::defer_lock); + boost::lock(this_lock, share_that_lock); + + for (unsigned i = 0; i < data_.size(); ++i) + data_[i] = (data_[i] + a.data_[i]) / 2; + + SharedLock share_this_lock(boost::move(this_lock)); + Lock that_lock(boost::move(share_that_lock)); + a.data_ = data_; + } +}; + +} // Assignment + +void temp() +{ + using namespace boost; + static upgrade_mutex mut; + unique_lock ul(mut); + shared_lock sl; + sl = BOOST_THREAD_MAKE_RV_REF(shared_lock(boost::move(ul))); +} + +int main() +{ + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + typedef boost::chrono::high_resolution_clock Clock; + typedef boost::chrono::duration sec; + Clock::time_point t0 = Clock::now(); + + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + S::test_shared_mutex(); + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + U::test_upgrade_mutex(); + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + Clock::time_point t1 = Clock::now(); + std::cout << sec(t1 - t0) << '\n'; + return 0; +} + +#else +#error "This platform doesn't support Boost.Chrono" +#endif diff --git a/src/boost/libs/thread/example/starvephil.cpp b/src/boost/libs/thread/example/starvephil.cpp new file mode 100644 index 000000000..467d0b3c4 --- /dev/null +++ b/src/boost/libs/thread/example/starvephil.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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 + +#include +#include +#include +#include +#include +#include + +namespace +{ +boost::mutex iomx; +} // namespace + +class canteen +{ +public: + canteen() : m_chickens(0) { } + + void get(int id) + { + boost::unique_lock lock(m_mutex); + while (m_chickens == 0) + { + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() << ") Phil" << id << + ": wot, no chickens? I'll WAIT ..." << std::endl; + } + m_condition.wait(lock); + } + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() << ") Phil" << id << + ": those chickens look good ... one please ..." << std::endl; + } + m_chickens--; + } + void put(int value) + { + boost::unique_lock lock(m_mutex); + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() + << ") Chef: ouch ... make room ... this dish is " + << "very hot ..." << std::endl; + } + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 3; + boost::thread::sleep(xt); + m_chickens += value; + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() << + ") Chef: more chickens ... " << m_chickens << + " now available ... NOTIFYING ..." << std::endl; + } + m_condition.notify_all(); + } + +private: + boost::mutex m_mutex; + boost::condition m_condition; + int m_chickens; +}; + +canteen g_canteen; + +void chef() +{ + const int chickens = 4; + { + boost::unique_lock lock(iomx); + std::cout << "(" << clock() << ") Chef: starting ..." << std::endl; + } + for (;;) + { + { + boost::unique_lock lock(iomx); + std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl; + } + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 2; + boost::thread::sleep(xt); + { + boost::unique_lock lock(iomx); + std::cout << "(" << clock() << ") Chef: " << chickens + << " chickens, ready-to-go ..." << std::endl; + } + g_canteen.put(chickens); + } +} + +struct phil +{ + phil(int id) : m_id(id) { } + void run() { + { + boost::unique_lock lock(iomx); + std::cout << "(" << clock() << ") Phil" << m_id + << ": starting ..." << std::endl; + } + for (;;) + { + if (m_id > 0) + { + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 3; + boost::thread::sleep(xt); + } + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() << ") Phil" << m_id + << ": gotta eat ..." << std::endl; + } + g_canteen.get(m_id); + { + boost::unique_lock lk(iomx); + std::cout << "(" << clock() << ") Phil" << m_id + << ": mmm ... that's good ..." << std::endl; + } + } + } + static void do_thread(void* param) { + static_cast(param)->run(); + } + + int m_id; +}; + +struct thread_adapt +{ + thread_adapt(void (*func)(void*), void* param) + : _func(func), _param(param) + { + } + int operator()() const + { + _func(_param); + return 0; + } + + void (*_func)(void*); + void* _param; +}; + +class thread_adapter +{ +public: + thread_adapter(void (*func)(void*), void* param) + : _func(func), _param(param) + { + } + void operator()() const { _func(_param); } +private: + void (*_func)(void*); + void* _param; +}; + +int main() +{ + boost::thread thrd_chef(&chef); + phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) }; + boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0])); + boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1])); + boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2])); + boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3])); + boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4])); + + thrd_chef.join(); + thrd_phil0.join(); + thrd_phil1.join(); + thrd_phil2.join(); + thrd_phil3.join(); + thrd_phil4.join(); + + return 0; +} diff --git a/src/boost/libs/thread/example/std_scoped_thread.cpp b/src/boost/libs/thread/example/std_scoped_thread.cpp new file mode 100644 index 000000000..5e9e7bd65 --- /dev/null +++ b/src/boost/libs/thread/example/std_scoped_thread.cpp @@ -0,0 +1,112 @@ +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente Botet +// +// 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) + +#if __cplusplus < 201103L +int main() +{ + return 0; +} +#else + +#define BOOST_THREAD_VERSION 3 + +#include +#include +#include +#include + +void do_something(int& i) +{ + ++i; +} +void f(int, int) +{ +} + +struct func +{ + int& i; + + func(int& i_) : + i(i_) + { + } + + void operator()() + { + for (unsigned j = 0; j < 1000000; ++j) + { + do_something(i); + } + } +}; + +void do_something_in_current_thread() +{ +} + +using strict_scoped_thread = boost::strict_scoped_thread; +using scoped_thread = boost::scoped_thread; + +int main() +{ + { + int some_local_state=0; + strict_scoped_thread t( (std::thread(func(some_local_state)))); + + do_something_in_current_thread(); + } + { + int some_local_state=0; + std::thread t(( func(some_local_state) )); + strict_scoped_thread g( (boost::move(t)) ); + + do_something_in_current_thread(); + } + { + int some_local_state=0; + std::thread t(( func(some_local_state) )); + strict_scoped_thread g( (std::move(t)) ); + + do_something_in_current_thread(); + } + { + int some_local_state=1; + scoped_thread t( (std::thread(func(some_local_state)))); + + if (t.joinable()) { + t.join(); + assert( ! t.joinable() ); + } + else + do_something_in_current_thread(); + } +#if 0 + try + { + int some_local_state=1; + std::thread t(( func(some_local_state) )); + scoped_thread g( (boost::move(t)) ); + if (g.joinable()) { + // CLANG crash here + g.detach(); + assert( ! g.joinable() ); + } + + do_something_in_current_thread(); + } + catch (...) { + assert( false); + } +#endif + { + scoped_thread g( &f, 1, 2 ); + do_something_in_current_thread(); + } + return 0; +} + +#endif diff --git a/src/boost/libs/thread/example/std_thread_guard.cpp b/src/boost/libs/thread/example/std_thread_guard.cpp new file mode 100644 index 000000000..ebf5a4173 --- /dev/null +++ b/src/boost/libs/thread/example/std_thread_guard.cpp @@ -0,0 +1,66 @@ +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente Botet +// +// 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) + +#if __cplusplus < 201103L +int main() +{ + return 0; +} +#else +#include +#include +#include +#include +#include + +void do_something(int& i) +{ + ++i; +} + +struct func +{ + int& i; + + func(int& i_):i(i_){} + + void operator()() + { + for(unsigned j=0;j<1000000;++j) + { + do_something(i); + } + } + +private: + func& operator=(func const&); + +}; + +void do_something_in_current_thread() +{} + +using thread_guard = boost::thread_guard; + + +void f() +{ + int some_local_state; + func my_func(some_local_state); + std::thread t(my_func); + thread_guard g(t); + + do_something_in_current_thread(); +} + +int main() +{ + f(); + return 0; +} + + +#endif diff --git a/src/boost/libs/thread/example/strict_lock.cpp b/src/boost/libs/thread/example/strict_lock.cpp new file mode 100644 index 000000000..43cfe5dfc --- /dev/null +++ b/src/boost/libs/thread/example/strict_lock.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2012 Vicente Botet +// +// 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 4 + +#include +#include +#include +#include +#include +#include + + +BOOST_STATIC_ASSERT(boost::is_strict_lock >::value); +BOOST_CONCEPT_ASSERT(( boost::BasicLockable )); +BOOST_CONCEPT_ASSERT(( boost::StrictLock > )); + +int main() +{ + { + boost::mutex mtx; + boost::strict_lock lk(mtx); + std::cout << __FILE__ << std::endl; + } + { + boost::timed_mutex mtx; + boost::unique_lock lk(mtx); + boost::nested_strict_lock > nlk(lk); + std::cout << __FILE__ << std::endl; + } + { + boost::mutex mtx; + boost::unique_lock lk(mtx, boost::defer_lock); + boost::nested_strict_lock > nlk(lk); + std::cout << __FILE__ << std::endl; + } + return 0; +} diff --git a/src/boost/libs/thread/example/synchronized_person.cpp b/src/boost/libs/thread/example/synchronized_person.cpp new file mode 100644 index 000000000..7930c0b00 --- /dev/null +++ b/src/boost/libs/thread/example/synchronized_person.cpp @@ -0,0 +1,282 @@ +// (C) Copyright 2012 Vicente Botet +// +// 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 4 + +#include +#include +#include + +//class SafePerson { +//public: +// std::string GetName() const { +// const_unique_access name(nameGuard); +// return *name; +// } +// void SetName(const std::string& newName) { +// unique_access name(nameGuard); +// *name = newName; +// } +//private: +// unique_access_guard nameGuard; +//}; + +class SafePerson { +public: + std::string GetName() const { + return *name; + } + void SetName(const std::string& newName) { + *name = newName; + } + +private: + boost::synchronized_value name; +}; + +class Person { +public: + std::string GetName() const { + return name; + } + void SetName(const std::string& newName) { + name = newName; + } +private: + std::string name; +}; +typedef boost::synchronized_value Person_ts; + + +//class SafeMemberPerson { +//public: +// SafeMemberPerson(unsigned int age) : +// memberGuard(age) +// { } +// std::string GetName() const { +// const_unique_access member(memberGuard); +// return member->name; +// } +// void SetName(const std::string& newName) { +// unique_access member(memberGuard); +// member->name = newName; +// } +//private: +// struct Member +// { +// Member(unsigned int age) : +// age(age) +// { } +// std::string name; +// unsigned int age; +// }; +// unique_access_guard memberGuard; +//}; + +class SafeMemberPerson { +public: + SafeMemberPerson(unsigned int age) : + member(Member(age)) + { } + std::string GetName() const { + return member->name; + } + void SetName(const std::string& newName) { + member->name = newName; + } +private: + struct Member { + Member(unsigned int age) : + age(age) + { } + std::string name; + unsigned int age; + }; + boost::synchronized_value member; +}; + + +class Person2 { +public: + Person2(unsigned int age) : age_(age) + {} + std::string GetName() const { + return name_; + } + void SetName(const std::string& newName) { + name_ = newName; + } + unsigned int GetAge() const { + return age_; + } + +private: + std::string name_; + unsigned int age_; +}; +typedef boost::synchronized_value Person2_ts; + +//=================== + +//class HelperPerson { +//public: +// HelperPerson(unsigned int age) : +// memberGuard(age) +// { } +// std::string GetName() const { +// const_unique_access member(memberGuard); +// Invariant(member); +// return member->name; +// } +// void SetName(const std::string& newName) { +// unique_access member(memberGuard); +// Invariant(member); +// member->name = newName; +// } +//private: +// void Invariant(const_unique_access& member) const { +// if (member->age < 0) throw std::runtime_error("Age cannot be negative"); +// } +// struct Member { +// Member(unsigned int age) : +// age(age) +// { } +// std::string name; +// unsigned int age; +// }; +// unique_access_guard memberGuard; +//}; + +class HelperPerson { +public: + HelperPerson(unsigned int age) : + member(age) + { } + std::string GetName() const { +#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + auto memberSync = member.synchronize(); +#else + boost::const_strict_lock_ptr memberSync = member.synchronize(); +#endif + Invariant(memberSync); + return memberSync->name; + } + void SetName(const std::string& newName) { +#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + auto memberSync = member.synchronize(); +#else + boost::strict_lock_ptr memberSync = member.synchronize(); +#endif + Invariant(memberSync); + memberSync->name = newName; + } +private: + struct Member { + Member(unsigned int age) : + age(age) + { } + std::string name; + unsigned int age; + }; + void Invariant(boost::const_strict_lock_ptr & mbr) const + { + if (mbr->age < 1) throw std::runtime_error("Age cannot be negative"); + } + boost::synchronized_value member; +}; + +class Person3 { +public: + Person3(unsigned int age) : + age_(age) + { } + std::string GetName() const { + Invariant(); + return name_; + } + void SetName(const std::string& newName) { + Invariant(); + name_ = newName; + } +private: + std::string name_; + unsigned int age_; + void Invariant() const { + if (age_ < 1) throw std::runtime_error("Age cannot be negative"); + } +}; + +typedef boost::synchronized_value Person3_ts; + +int main() +{ + { + SafePerson p; + p.SetName("Vicente"); + } + { + Person_ts p; + p->SetName("Vicente"); + } + { + SafeMemberPerson p(1); + p.SetName("Vicente"); + } + { + Person2_ts p(1); + p->SetName("Vicente"); + } + { + HelperPerson p(1); + p.SetName("Vicente"); + } + { + Person3_ts p(1); + p->SetName("Vicente"); + } + { + Person3_ts p1(1); + Person3_ts p2(2); + Person3_ts p3(3); +#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + auto lk1 = p1.unique_synchronize(boost::defer_lock); + auto lk2 = p2.unique_synchronize(boost::defer_lock); + auto lk3 = p3.unique_synchronize(boost::defer_lock); +#else + boost::unique_lock_ptr lk1 = p1.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr lk2 = p2.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr lk3 = p3.unique_synchronize(boost::defer_lock); +#endif + boost::lock(lk1,lk2,lk3); + + lk1->SetName("Carmen"); + lk2->SetName("Javier"); + lk3->SetName("Matias"); + } +#if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS \ +&& ! defined(BOOST_THREAD_NO_SYNCHRONIZE) + { + Person3_ts p1(1); + Person3_ts p2(2); + Person3_ts p3(3); + + auto t = boost::synchronize(p1,p2,p3); + std::get<0>(t)->SetName("Carmen"); + std::get<1>(t)->SetName("Javier"); + std::get<2>(t)->SetName("Matias"); + } + { + const Person3_ts p1(1); + Person3_ts p2(2); + const Person3_ts p3(3); + + auto t = boost::synchronize(p1,p2,p3); + //std::get<0>(t)->SetName("Carmen"); + std::get<1>(t)->SetName("Javier"); + //std::get<2>(t)->SetName("Matias"); + } +#endif + return 0; +} diff --git a/src/boost/libs/thread/example/synchronized_value.cpp b/src/boost/libs/thread/example/synchronized_value.cpp new file mode 100644 index 000000000..61480a57c --- /dev/null +++ b/src/boost/libs/thread/example/synchronized_value.cpp @@ -0,0 +1,147 @@ +// (C) Copyright 2010 Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk +// (C) Copyright 2012 Vicente Botet +// +// 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 4 + +#include +#include +#include + + void addTrailingSlashIfMissing(boost::synchronized_value & path) + { + boost::strict_lock_ptr u=path.synchronize(); + + if(u->empty() || (*u->rbegin()!='/')) + { + *u+='/'; + } + } + +void f(const boost::synchronized_value &v) { + std::cout<<"v="<<*v< &v) { + std::cout<<"v="<<*v< & path) +{ + boost::strict_lock_ptr u=path.synchronize(); + + return (u->empty() || (*u->rbegin()!='/')); +} + +int main() +{ + { + boost::synchronized_value v1; + *v1=42; + std::cout<<"v1="<<*v1<append("foo"); + addTrailingSlashIfMissing(s); + std::cout<<"s="< s; + s = std::string("foo/"); + std::cout<<"ss="<< s << std::endl; + } + { + boost::synchronized_value s; + s = "foo/"; + std::cout<<"ss="<< s << std::endl; + } + { + boost::synchronized_value s1("a"); + boost::synchronized_value s2; + s2=s1; + std::cout<<"s1="<< s1 << std::endl; + std::cout<<"s2="<< s2 << std::endl; + } + { + boost::synchronized_value s1("a"); + boost::synchronized_value s2("b"); + std::cout<<"s1="<< s1 << std::endl; + std::cout<<"s2="<< s2 << std::endl; + swap(s1,s2); + std::cout<<"s1="<< s1 << std::endl; + std::cout<<"s2="<< s2 << std::endl; + } +#if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + { + boost::synchronized_value sts("a"); + std::string s(sts); + std::cout<<"ssts="<< s << std::endl; + } +#endif + { + boost::synchronized_value s1(1); + boost::synchronized_value s2(1); + BOOST_ASSERT(s1==s2); + BOOST_ASSERT(s1<=s2); + BOOST_ASSERT(s1>=s2); + BOOST_ASSERT(s1==1); + BOOST_ASSERT(s1<=1); + BOOST_ASSERT(s1>=1); + } + { + boost::synchronized_value s1(1); + boost::synchronized_value s2(2); + BOOST_ASSERT(s1!=s2); + BOOST_ASSERT(s1!=2); + BOOST_ASSERT(2!=s1); + } + { + boost::synchronized_value s1(1); + boost::synchronized_value s2(2); + BOOST_ASSERT(s1s1); + BOOST_ASSERT(s2>=s1); + BOOST_ASSERT(s1<2); + BOOST_ASSERT(s1<=2); + BOOST_ASSERT(s2>1); + BOOST_ASSERT(s2>=1); + } + return 0; +} + diff --git a/src/boost/libs/thread/example/tennis.cpp b/src/boost/libs/thread/example/tennis.cpp new file mode 100644 index 000000000..d560ecb92 --- /dev/null +++ b/src/boost/libs/thread/example/tennis.cpp @@ -0,0 +1,137 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#undef BOOST_THREAD_VERSION +#define BOOST_THREAD_VERSION 2 + +#include +#include +#include +#include +#include + +#if defined(BOOST_HAS_WINTHREADS) +# include +# include +#endif + +enum game_state +{ + START, + PLAYER_A, + PLAYER_B, + GAME_OVER, + ONE_PLAYER_GONE, + BOTH_PLAYERS_GONE +}; + +int state; +boost::mutex mutex; +boost::condition cond; + +const char* player_name(int state) +{ + if (state == PLAYER_A) + return "PLAYER-A"; + if (state == PLAYER_B) + return "PLAYER-B"; + throw "bad player"; + //return 0; +} + +void player(int active) +{ + boost::unique_lock lock(mutex); + + int other = active == PLAYER_A ? PLAYER_B : PLAYER_A; + + while (state < GAME_OVER) + { + //std::cout << player_name(active) << ": Play." << std::endl; + state = other; + cond.notify_all(); + do + { + cond.wait(lock); + if (state == other) + { + std::cout << "---" << player_name(active) + << ": Spurious wakeup!" << std::endl; + } + } while (state == other); + } + + ++state; + std::cout << player_name(active) << ": Gone." << std::endl; + cond.notify_all(); +} + +struct thread_adapt +{ + thread_adapt(void (*func)(void*), void* param) + : _func(func), _param(param) + { + } + int operator()() const + { + _func(_param); + return 0; + } + + void (*_func)(void*); + void* _param; +}; + +class thread_adapter +{ +public: + thread_adapter(void (*func)(void*), void* param) + : _func(func), _param(param) + { + } + void operator()() const { _func(_param); } +private: + void (*_func)(void*); + void* _param; +}; + +int main() +{ + state = START; + + boost::thread thrda(&player, PLAYER_A); + boost::thread thrdb(&player, PLAYER_B); + + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 1; + boost::thread::sleep(xt); + { + boost::unique_lock lock(mutex); + std::cout << "---Noise ON..." << std::endl; + } + + for (int i = 0; i < 10; ++i) + cond.notify_all(); + + { + boost::unique_lock lock(mutex); + std::cout << "---Noise OFF..." << std::endl; + state = GAME_OVER; + cond.notify_all(); + do + { + cond.wait(lock); + } while (state != BOTH_PLAYERS_GONE); + } + + std::cout << "GAME OVER" << std::endl; + + thrda.join(); + thrdb.join(); + + return 0; +} diff --git a/src/boost/libs/thread/example/this_executor.cpp b/src/boost/libs/thread/example/this_executor.cpp new file mode 100644 index 000000000..e573f05c1 --- /dev/null +++ b/src/boost/libs/thread/example/this_executor.cpp @@ -0,0 +1,85 @@ +// Copyright (C) 2014 Vicente Botet +// +// 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) + +#include +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 5 +#define BOOST_THREAD_USES_LOG_THREAD_ID + +#include +#include +#include +#include +#include +#include +#include + +#include + +struct current_executor_state_type { + boost::shared_ptr current_executor_ptr; + + template + void set_current_executor(Executor& ex) + { + current_executor_ptr = boost::make_shared(ex); + } + boost::generic_executor_ref current_executor() + { + if (current_executor_ptr) + return *current_executor_ptr; + else + throw ""; + } +}; + +thread_local current_executor_state_type current_executor_state; + +boost::generic_executor_ref current_executor() +{ + return current_executor_state.current_executor(); +} + +void p2() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + + +void p1() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + current_executor().submit(&p2); + boost::this_thread::sleep_for(boost::chrono::milliseconds(400)); + std::cout << BOOST_CONTEXTOF << std::endl; +} + +int main() +{ + std::cout << BOOST_CONTEXTOF << std::endl; + + boost::basic_thread_pool tp(4, + // at_thread_entry + [](boost::basic_thread_pool& pool) + { + current_executor_state.set_current_executor(pool); + } + ); + + tp.submit(&p1); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + std::cout << BOOST_CONTEXTOF << std::endl; + + return 1; + +} diff --git a/src/boost/libs/thread/example/thread.cpp b/src/boost/libs/thread/example/thread.cpp new file mode 100644 index 000000000..d6bc6f23f --- /dev/null +++ b/src/boost/libs/thread/example/thread.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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 + +#include +#include +#include + +struct thread_alarm +{ + thread_alarm(int secs) : m_secs(secs) { } + void operator()() + { + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += m_secs; + + boost::thread::sleep(xt); + + std::cout << "alarm sounded..." << std::endl; + } + + int m_secs; +}; + +int main() +{ + int secs = 5; + std::cout << "setting alarm for 5 seconds..." << std::endl; + thread_alarm alarm(secs); + boost::thread thrd(alarm); + thrd.join(); +} diff --git a/src/boost/libs/thread/example/thread_group.cpp b/src/boost/libs/thread/example/thread_group.cpp new file mode 100644 index 000000000..1256a1045 --- /dev/null +++ b/src/boost/libs/thread/example/thread_group.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#include +#include +#include + +int count = 0; +boost::mutex mutex; + +void increment_count() +{ + boost::unique_lock lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +boost::thread_group threads2; +boost::thread* th2 = 0; + +void increment_count_2() +{ + boost::unique_lock lock(mutex); + BOOST_TEST(threads2.is_this_thread_in()); + std::cout << "count = " << ++count << std::endl; +} + +int main() +{ + { + boost::thread_group threads; + for (int i = 0; i < 3; ++i) + threads.create_thread(&increment_count); + threads.join_all(); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + { + boost::thread_group threads; + for (int i = 0; i < 3; ++i) + threads.create_thread(&increment_count); + threads.interrupt_all(); + threads.join_all(); + } +#endif + { + boost::thread_group threads; + boost::thread* th = new boost::thread(&increment_count); + threads.add_thread(th); + BOOST_TEST(! threads.is_this_thread_in()); + threads.join_all(); + } + { + boost::thread_group threads; + boost::thread* th = new boost::thread(&increment_count); + threads.add_thread(th); + BOOST_TEST(threads.is_thread_in(th)); + threads.remove_thread(th); + BOOST_TEST(! threads.is_thread_in(th)); + th->join(); + delete th; + } + { + { + boost::unique_lock lock(mutex); + boost::thread* th2 = new boost::thread(&increment_count_2); + threads2.add_thread(th2); + } + threads2.join_all(); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/example/thread_guard.cpp b/src/boost/libs/thread/example/thread_guard.cpp new file mode 100644 index 000000000..a8b285deb --- /dev/null +++ b/src/boost/libs/thread/example/thread_guard.cpp @@ -0,0 +1,58 @@ +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente Botet +// +// 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) + + +#include +#include +#include +#include + +void do_something(int& i) +{ + ++i; +} + +struct func +{ + int& i; + + func(int& i_):i(i_){} + func(func const& other):i(other.i){} + + void operator()() + { + for(unsigned j=0;j<1000000;++j) + { + do_something(i); + } + } + +private: + func& operator=(func const&); + +}; + +void do_something_in_current_thread() +{} + + +void f() +{ + int some_local_state; + func my_func(some_local_state); + boost::thread t(my_func); + boost::thread_guard<> g(t); + + do_something_in_current_thread(); +} + +int main() +{ + f(); + return 0; +} + + diff --git a/src/boost/libs/thread/example/thread_pool.cpp b/src/boost/libs/thread/example/thread_pool.cpp new file mode 100644 index 000000000..bf9b64e1d --- /dev/null +++ b/src/boost/libs/thread/example/thread_pool.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2012-2013 Vicente Botet +// +// 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) + +#include + +#define BOOST_THREAD_VERSION 5 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#define BOOST_THREAD_QUEUE_DEPRECATE_OLD +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +void p1() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG; +} + +void p2() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG; +} + +void submit_some(boost::basic_thread_pool& tp) { + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); +} + + +int main() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " " << BOOST_THREAD_END_LOG; + return 0; +} diff --git a/src/boost/libs/thread/example/tss.cpp b/src/boost/libs/thread/example/tss.cpp new file mode 100644 index 000000000..f5f108e11 --- /dev/null +++ b/src/boost/libs/thread/example/tss.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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) + +#include +#include +#include + +boost::thread_specific_ptr value; + +void increment() +{ + int* p = value.get(); + ++*p; +} + +void thread_proc() +{ + value.reset(new int(0)); // initialize the thread's storage + for (int i=0; i<10; ++i) + { + increment(); + int* p = value.get(); + assert(*p == i+1); + (void)(p); + } +} + +int main() +{ + boost::thread_group threads; + for (int i=0; i<5; ++i) + threads.create_thread(&thread_proc); + threads.join_all(); +} diff --git a/src/boost/libs/thread/example/user_scheduler.cpp b/src/boost/libs/thread/example/user_scheduler.cpp new file mode 100644 index 000000000..7bb02602b --- /dev/null +++ b/src/boost/libs/thread/example/user_scheduler.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2013 Vicente Botet +// +// 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) + +#include + +#define BOOST_THREAD_VERSION 5 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +void p1() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " P1" << BOOST_THREAD_END_LOG; +} + +void p2() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " P2" << BOOST_THREAD_END_LOG; +} + +void submit_some(boost::loop_executor& tp) { + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); + tp.submit(&p1); + tp.submit(&p2); +} + +int main() +{ + BOOST_THREAD_LOG + << boost::this_thread::get_id() << " " << BOOST_THREAD_END_LOG; + return 0; +} diff --git a/src/boost/libs/thread/example/with_lock_guard.cpp b/src/boost/libs/thread/example/with_lock_guard.cpp new file mode 100644 index 000000000..f3a4cd806 --- /dev/null +++ b/src/boost/libs/thread/example/with_lock_guard.cpp @@ -0,0 +1,53 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 Vicente Botet +// +// 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) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include // std::cout +#include +#include + +boost::mutex m; // protection for 'x' and 'std::cout' +int x; + +#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700) +void print_x() { + ++x; + std::cout << "x = " << x << std::endl; +} + +void job() { + for (int i = 0; i < 10; ++i) { + boost::with_lock_guard(m, print_x); + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + } +} +#else +void job() { + for (int i = 0; i < 10; ++i) { + boost::with_lock_guard( + m, + []() { + ++x; + std::cout << "x = " << x << std::endl; + } + ); + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + } +} +#endif + +int main() { +#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700) + std::cout << "(no lambdas)" << std::endl; +#endif + boost::scoped_thread<> thread_1((boost::thread(job))); + boost::scoped_thread<> thread_2((boost::thread(job))); + boost::scoped_thread<> thread_3((boost::thread(job))); + return 0; +} diff --git a/src/boost/libs/thread/example/xtime.cpp b/src/boost/libs/thread/example/xtime.cpp new file mode 100644 index 000000000..a873085b3 --- /dev/null +++ b/src/boost/libs/thread/example/xtime.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// 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 + +#include +#include + +int main() +{ + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 1; + boost::thread::sleep(xt); // Sleep for 1 second +} -- cgit v1.2.3