diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/thread | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/thread')
504 files changed, 55171 insertions, 0 deletions
diff --git a/src/boost/libs/thread/README.md b/src/boost/libs/thread/README.md new file mode 100644 index 000000000..190775925 --- /dev/null +++ b/src/boost/libs/thread/README.md @@ -0,0 +1,10 @@ +thread +====== + +Portable C++ multi-threading. C++11, C++14. + +### License + +Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt). + + diff --git a/src/boost/libs/thread/build/Jamfile.v2 b/src/boost/libs/thread/build/Jamfile.v2 new file mode 100644 index 000000000..1a88d0102 --- /dev/null +++ b/src/boost/libs/thread/build/Jamfile.v2 @@ -0,0 +1,319 @@ +# $Id$ +# Copyright 2006-2007 Roland Schwarz. +# Copyright 2007 Anthony Williams +# Copyright 2011-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) + +######################################################################### +# The boost threading library can be built on top of different API's +# Currently this is the win32 API and the pthreads API. +# Pthread is native on unix variants. +# To get pthread on windows you need the pthread win32 library +# http://sourceware.org/pthreads-win32 which is available under LGPL. +# +# You need to provide the include path and lib path in the variables +# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these +# paths in site-config.jam, user-config.jam or in the environment. +# A new feature is provided to request a specific API: +# <threadapi>win32 and <threadapi>pthread. +# +# The naming of the resulting libraries is mostly the same for the +# variant native to the build platform, i.e. +# boost_thread and the boost specific tagging. +# For the library variant that is not native on the build platform +# an additional tag is applied: +# boost_thread_pthread for the pthread variant on windows, and +# boost_thread_win32 for the win32 variant (likely when built on cygwin). +# +# To request the pthread variant on windows, from boost root you would +# say e.g: +# bjam msvc-8.0 --with-thread install threadapi=pthread +######################################################################### + +import os ; +import indirect ; +import path ; +import configure ; +import threadapi-feature ; + +exe has_atomic_flag_lockfree : ../build/has_atomic_flag_lockfree_test.cpp ; + +project boost/thread + : source-location ../src + : requirements <threading>multi + #<link>static:<define>BOOST_THREAD_STATIC_LINK=1 + #<link>shared:<define>BOOST_THREAD_DYN_LINK=1 + <link>static:<define>BOOST_THREAD_BUILD_LIB=1 + <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 + -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag + <tag>@$(__name__).tag + <toolset>gcc:<cxxflags>-Wno-long-long + #<define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + #<define>BOOST_SYSTEM_NO_DEPRECATED + #<define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + + #-pedantic -ansi -std=gnu++0x -Wextra -fpermissive + <warnings>all + <toolset>gcc:<cxxflags>-Wextra + <toolset>gcc:<cxxflags>-pedantic + <toolset>gcc:<cxxflags>-Wno-long-long + #<toolset>gcc:<cxxflags>-ansi + #<toolset>gcc:<cxxflags>-fpermissive + <toolset>gcc-4:<cxxflags>-Wno-variadic-macros + <toolset>gcc-5:<cxxflags>-Wno-variadic-macros + #<toolset>gcc:<cxxflags>-Wunused-local-typedefs + <toolset>gcc:<cxxflags>-Wunused-function + <toolset>gcc:<cxxflags>-Wno-unused-parameter + + <toolset>darwin:<cxxflags>-Wextra + <toolset>darwin:<cxxflags>-pedantic + #<toolset>darwin:<cxxflags>-ansi + <toolset>darwin:<cxxflags>-fpermissive + <toolset>darwin:<cxxflags>-Wno-long-long + #<toolset>darwin:<cxxflags>-Wno-variadic-macros + <toolset>darwin-4:<cxxflags>-Wno-variadic-macros + <toolset>darwin-5:<cxxflags>-Wno-variadic-macros + #<toolset>darwin:<cxxflags>-Wunused-local-typedefs + <toolset>darwin:<cxxflags>-Wunused-function + <toolset>darwin:<cxxflags>-Wno-unused-parameter + + #<toolset>pathscale:<cxxflags>-Wextra + <toolset>pathscale:<cxxflags>-Wno-long-long + <toolset>pathscale:<cxxflags>-pedantic + + <toolset>clang:<warnings>on + <toolset>clang:<cxxflags>-Wextra + #<toolset>clang:<cxxflags>-ansi + #<toolset>clang:<cxxflags>-fpermissive + <toolset>clang:<cxxflags>-Wno-long-long + <toolset>clang:<cxxflags>-Wunused-function + <toolset>clang:<cxxflags>-Wno-variadic-macros + <toolset>clang:<cxxflags>-Wno-unused-parameter + + #<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc:<cxxflags>-Wno-missing-field-initializers + + <toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor + <toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor + + #<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.8:<cxxflags>-Wno-unused-function + #<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.9:<cxxflags>-Wno-unused-function + <toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-3.0:<cxxflags>-Wno-unused-function + #<toolset>clang-3.0:<cxxflags>-Wno-unused-variable + +# Note: Some of the remarks from the Intel compiler are disabled +# remark #193: zero used for undefined preprocessing identifier "XXX" +# remark #304: access control not specified ("public" by default) +# remark #593: variable "XXX" was set but never used +# remark #1418: external function definition with no prior declaration +# remark #2415: variable "XXX" of static storage duration was declared but never referenced + + <toolset>intel:<cxxflags>-wd193,304,383,444 + <toolset>intel:<cxxflags>-wd593,981 + <toolset>intel:<cxxflags>-wd1418 + <toolset>intel:<cxxflags>-wd2415 + + <toolset>msvc:<cxxflags>/wd4100 + <toolset>msvc:<cxxflags>/wd4512 + <toolset>msvc:<cxxflags>/wd6246 + + <target-os>windows:<define>WIN32_LEAN_AND_MEAN + <target-os>windows:<define>BOOST_USE_WINDOWS_H + + # : default-build <threading>multi + : usage-requirements # pass these requirement to dependents (i.e. users) + #<link>static:<define>BOOST_THREAD_STATIC_LINK=1 + #<link>shared:<define>BOOST_THREAD_DYN_LINK=1 + <link>static:<define>BOOST_THREAD_BUILD_LIB=1 + <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 + #<define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + #<define>BOOST_SYSTEM_NO_DEPRECATED + #<define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + ; + +rule tag ( name : type ? : property-set ) +{ + local result = $(name) ; + + if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB + { + local api = [ $(property-set).get <threadapi> ] ; + + # non native api gets additional tag + if $(api) != [ threadapi-feature.get-default $(property-set) ] { + result = $(result)_$(api) ; + } + } + + # forward to the boost tagging rule + return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag + $(result) : $(type) : $(property-set) ] ; +} + +rule win32_pthread_paths ( properties * ) +{ + local result ; + local PTW32_INCLUDE ; + local PTW32_LIB ; + PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ; + PTW32_LIB = [ modules.peek : PTW32_LIB ] ; + PTW32_INCLUDE ?= [ modules.peek user-config : PTW32_INCLUDE ] ; + PTW32_LIB ?= [ modules.peek user-config : PTW32_LIB ] ; + PTW32_INCLUDE ?= [ modules.peek site-config : PTW32_INCLUDE ] ; + PTW32_LIB ?= [ modules.peek site-config : PTW32_LIB ] ; + + if ! ( $(PTW32_INCLUDE) && $(PTW32_LIB) ) + { + if ! $(.notified) + { + echo "************************************************************" ; + echo "Trying to build Boost.Thread with pthread support." ; + echo "If you need pthread you should specify the paths." ; + echo "You can specify them in site-config.jam, user-config.jam" ; + echo "or in the environment." ; + echo "For example:" ; + echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ; + echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib" ; + echo "************************************************************" ; + .notified = true ; + } + } + else + { + local include_path = [ path.make $(PTW32_INCLUDE) ] ; + local lib_path = [ path.make $(PTW32_LIB) ] ; + local libname = pthread ; + if <toolset>msvc in $(properties) + { + libname = $(libname)VC2.lib ; + } + if <toolset>gcc in $(properties) + { + libname = lib$(libname)GC2.a ; + } + lib_path = [ path.glob $(lib_path) : $(libname) ] ; + if ! $(lib_path) + { + if ! $(.notified) + { + echo "************************************************************" ; + echo "Trying to build Boost.Thread with pthread support." ; + echo "But the library" $(libname) "could not be found in path" ; + echo $(PTW32_LIB) ; + echo "************************************************************" ; + .notified = true ; + } + } + else + { + result += <include>$(include_path) ; + result += <library>$(lib_path) ; + } + } + return $(result) ; +} + +rule usage-requirements ( properties * ) +{ + local result ; + if <threadapi>pthread in $(properties) + { + result += <define>BOOST_THREAD_POSIX ; + if <target-os>windows in $(properties) + { + result += [ win32_pthread_paths $(properties) ] ; + # TODO: What is for static linking? Is the <library> also needed + # in that case? + } + } + if <threadapi>win32 in $(properties) + { + result += <define>BOOST_THREAD_WIN32 ; + } + + #if ! <toolset>vacpp in $(properties) || <toolset-vacpp:version>11.1 in $(properties) || <toolset-vacpp:version>12.1.0.1 in $(properties) || <toolset-vacpp:version>12.1 in $(properties) + #{ + result += <library>/boost/chrono//boost_chrono ; + #} + + return $(result) ; +} + +rule requirements ( properties * ) +{ + local result ; + + if <threadapi>pthread in $(properties) + { + result += <define>BOOST_THREAD_POSIX ; + if <target-os>windows in $(properties) + { + local paths = [ win32_pthread_paths $(properties) ] ; + if $(paths) + { + result += $(paths) ; + } + else + { + result = <build>no ; + } + } + result += <define>BOOST_THREAD_DONT_USE_CHRONO ; + if ! [ configure.builds has_atomic_flag_lockfree + : $(properties) : "lockfree boost::atomic_flag" ] { + result += <library>/boost/atomic//boost_atomic ; + } + } else { + if <threadapi>win32 in $(properties) + { + result += <define>BOOST_THREAD_WIN32 ; + } + result += <define>BOOST_THREAD_USES_CHRONO ; + result += <library>/boost/chrono//boost_chrono ; + } + + return $(result) ; +} + +alias thread_sources + : ## win32 sources ## + win32/thread.cpp + win32/tss_dll.cpp + win32/tss_pe.cpp + win32/thread_primitives.cpp + future.cpp + : ## requirements ## + <threadapi>win32 + ; + +alias thread_sources + : ## pthread sources ## + pthread/thread.cpp + pthread/once.cpp + future.cpp + : ## requirements ## + <threadapi>pthread + ; + +explicit thread_sources ; + +lib boost_thread + : thread_sources + : <conditional>@requirements + : + : <link>shared:<define>BOOST_THREAD_USE_DLL=1 + <link>static:<define>BOOST_THREAD_USE_LIB=1 + <conditional>@usage-requirements + ; + +boost-install boost_thread ;
\ No newline at end of file diff --git a/src/boost/libs/thread/build/has_atomic_flag_lockfree_test.cpp b/src/boost/libs/thread/build/has_atomic_flag_lockfree_test.cpp new file mode 100644 index 000000000..ca6940546 --- /dev/null +++ b/src/boost/libs/thread/build/has_atomic_flag_lockfree_test.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2013, Petr Machata, Red Hat Inc. +// +// Use modification and distribution are subject to the boost Software +// License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +#include "../../../boost/atomic.hpp" +#include "../../../boost/static_assert.hpp" + +int main(int argc, char *argv[]) +{ + BOOST_STATIC_ASSERT(BOOST_ATOMIC_FLAG_LOCK_FREE); + return 0; +} 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 <library>../build//boost_thread <threading>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 <boost/thread/mutex.hpp> +#include <boost/thread/lockable_adapter.hpp> +#include <boost/thread/externally_locked.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <iostream> + +#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<mutex> +{ +public: + typedef basic_lockable_adapter<mutex> 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<BankAccount, AccountManager > checkingAcct_; + externally_locked<BankAccount, AccountManager > savingsAcct_; +}; +//] + +//[Checking2Savings +void AccountManager::Checking2Savings(int amount) +{ + strict_lock<AccountManager> 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<AccountManager> 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<AccountManager> guard1(*this); +// if (some_condition()) { +// guard1.lock(); +// } +// { +// strict_lock<AccountManager> guard(guard1); +// checkingAcct_.get(guard).Withdraw(amount); +// savingsAcct_.get(guard).Deposit(amount); +// } +// guard1.unlock(); +//} +////] +//#else +////[AMoreComplicatedChecking2Savings +void AccountManager::AMoreComplicatedChecking2Savings(int amount) { + unique_lock<AccountManager> guard1(*this); + if (some_condition()) { + guard1.lock(); + } + { + nested_strict_lock<unique_lock<AccountManager> > 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 <iostream> +#include <vector> +#include <boost/utility.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/thread_only.hpp> +#include "../test/remove_error_code_unused_warning.hpp" + +class bounded_buffer : private boost::noncopyable +{ +public: + typedef boost::unique_lock<boost::mutex> 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<int>::size_type buffered; + std::vector<int> 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<boost::mutex> 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<boost::mutex> 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 <boost/config.hpp> +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/generic_executor_ref.hpp> +#include <string> +#include <iostream> + +#include <boost/thread/caller_context.hpp> + + +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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include <iostream> + +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/loop_executor.hpp> +#include <boost/thread/executors/serial_executor.hpp> +#include <boost/thread/executors/inline_executor.hpp> +#include <boost/thread/executors/thread_executor.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/executor_adaptor.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> +#include <cassert> + +boost::future<void> p(boost::future<void> 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<int> t1 = boost::async(ea, &f1); + boost::future<int> 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<int> t1 = boost::async(ea3, &f1); + std::cout << BOOST_CONTEXTOF << std::endl; + boost::future<int> t2 = boost::async(ea3, &f1); + std::cout << BOOST_CONTEXTOF << std::endl; + //boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11 + //boost::future<int> 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<int> 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/experimental/task_region.hpp> +#include <iostream> + +#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 <class Ex> +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<Ex>& 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 <boost/config.hpp> +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <exception> +#include <string> +#include <iostream> + +#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 << "<MAIN" << BOOST_THREAD_END_LOG; + + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> f1 = boost::async(&p1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> f1 = boost::async(boost::launch::async, &p1_ex); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << __FILE__ << "["<< __LINE__<<"] " << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + } + BOOST_THREAD_LOG << "MAIN>" << 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 <boost/config.hpp> +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> +#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<int> f) +{ + BOOST_THREAD_LOG << "P2<" << BOOST_THREAD_END_LOG; + try + { + return 2 * f.get(); + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl; + 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<int> f) +{ + BOOST_THREAD_LOG << "<P2S" << BOOST_THREAD_END_LOG; + try + { + return 2 * f.get(); + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl; + 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 << "P2S>" << BOOST_THREAD_END_LOG; + return 0; +} + +int main() +{ + const int number_of_tests = 100; + BOOST_THREAD_LOG << "<MAIN" << BOOST_THREAD_END_LOG; + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> f1 = boost::async(&p1); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + 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; + } + } + { + for (int i=0; i< number_of_tests; i++) + try + { + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::shared_future<int> f1 = boost::async(&p1).share(); + BOOST_THREAD_LOG << "" << BOOST_THREAD_END_LOG; + boost::future<int> 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 "<<ex.what() << "" << std::endl; + 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 + +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 <boost/config.hpp> +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> + +#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<int> p2() +{ + BOOST_THREAD_LOG << "<P2" << BOOST_THREAD_END_LOG; + boost::future<int> 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 << "<MAIN" << BOOST_THREAD_END_LOG; + for (int i=0; i< number_of_tests; i++) + try + { + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + boost::future<int> 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<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2); + boost::future<int> inner_future = outer_future.unwrap(); + inner_future.wait(); + int ii = inner_future.get(); + BOOST_THREAD_LOG << "ii= "<< ii << "" << BOOST_THREAD_END_LOG; + } + { + boost::future<boost::future<int> > outer_future = boost::async(boost::launch::async, &p2); + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + BOOST_THREAD_LOG << "MAIN>" << 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 <boost/config.hpp> + +#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 <boost/thread/future.hpp> +#include <boost/thread/csbl/vector.hpp> +#include <boost/assert.hpp> +#include <boost/thread/detail/log.hpp> +#include <string> +#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<int> 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<int> 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 main() +{ + BOOST_THREAD_LOG + << "<MAIN" << BOOST_THREAD_END_LOG; + { + try + { + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<boost::csbl::tuple<> > all0 = boost::when_all(); + BOOST_THREAD_LOG + << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + boost::csbl::tuple<boost::future<int> > 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<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::tuple<boost::future<int> > 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<int> f1 = boost::make_ready_future(1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + boost::csbl::tuple<boost::future<int> > 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<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<int> f2 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + //(void) all.wait(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<std::string> f2 = boost::make_ready_future(std::string("nnnnnnn"));; + boost::future<boost::csbl::tuple<boost::future<int>, boost::future<std::string> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + //(void) all.wait(); + boost::csbl::tuple<boost::future<int>, boost::future<std::string> > 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<boost::future<int> > 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<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector<boost::future<int> > 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<boost::csbl::tuple<> > all0 = boost::when_any(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + boost::csbl::tuple<boost::future<int> > 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<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + boost::csbl::tuple<boost::future<int> > 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<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<int> f2 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<int> f1 = boost::make_ready_future(1); + boost::future<int> f2 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<std::string> f1 = boost::make_ready_future(std::string("aaaa")); + boost::future<int> f2 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<std::string>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<std::string>,boost::future<int> > 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<int> f2 = boost::make_ready_future(1); + boost::future<int> f1 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::async, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p1b); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + boost::csbl::tuple<boost::future<int>,boost::future<int> > 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<boost::future<int> > 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<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::csbl::vector<boost::future<int> > 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 <boost/thread/csbl/vector.hpp> +using namespace boost; + +void f( boost::csbl::vector<future<int> > &//vec + , BOOST_THREAD_RV_REF(future<int>) //f + ) { +} +int main() +{ + boost::csbl::vector<future<int> > 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 <boost/config.hpp> +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/loop_executor.hpp> +#include <boost/thread/executors/serial_executor.hpp> +#include <boost/thread/executors/inline_executor.hpp> +#include <boost/thread/executors/thread_executor.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/executor_adaptor.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> + +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<int> t1 = boost::async(ea, &f1); + boost::future<int> 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<int> t1 = boost::async(ea3, &f1); + boost::future<int> t2 = boost::async(ea3, &f1); + //boost::future<int> t2 = boost::async(ea3, f2, 1); // todo this doesn't compiles yet on C++11 + //boost::future<int> 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<int> 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 <boost/config.hpp> +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> + +#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 << "<MAIN" << BOOST_THREAD_END_LOG; + + for (int i=0; i< number_of_tests; i++) + try + { + { + boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;}); + int result = f1.get(); + BOOST_THREAD_LOG << "f1 " << result << BOOST_THREAD_END_LOG; + } + { + boost::future<int> f1 = boost::async(boost::launch::async, []() {return 123;}); + boost::future<int> f2 = f1.then([](boost::future<int> 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<int> f1 = boost::async(boost::launch::async, []() {return 123;}); + boost::future<int> 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 "<<ex.what() << "" << std::endl; + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + return 1; + } + catch (...) + { + std::cout << " ERRORRRRR exception thrown" << std::endl; + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + return 2; + } + BOOST_THREAD_LOG << "MAIN>" << 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <iostream> + +namespace boost +{ + + template <typename T> + 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> void_compute() +{ + return BOOST_THREAD_MAKE_RV_REF(boost::make_ready_future()); +} +#endif + +boost::future<int> 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<int>(std::logic_error("Error")); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + //boost::future<int> f1 = boost::async([]() { return x+1; }); + boost::future<int> f1 = boost::async(p1); + return boost::move(f1); +} + +boost::future<int&> compute_ref(int x) +{ + static int i = 0; + //if (x == 0) return boost::make_ready_future<int&>(i); //This must not compile as the type is deduced as boost::future<int> + if (x == 0) return boost::make_ready_no_decay_future<int&>(i); +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + if (x < 0) return boost::make_exceptional_future<int&>(std::logic_error("Error")); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + boost::future<int&> f1 = boost::async(p1r); + return boost::move(f1); +} + +boost::shared_future<int> 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<int>(std::logic_error("Error")).share(); +#else + if (x < 0) return boost::make_exceptional(std::logic_error("Error")); +#endif + //boost::future<int> f1 = boost::async([]() { return x+1; }); + boost::shared_future<int> 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<int> f = boost::async(boost::launch::async, p1); +// std::cout << i << " "<<f.get() << std::endl; +// } +#if defined BOOST_THREAD_USES_MOVE + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future<void> f = void_compute(); + f.get(); + } +#endif + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future<int> f = compute(-1); + f.wait(); + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future<int> f = compute(0); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future<int&> f = compute_ref(0); + std::cout << f.get() << std::endl; + } +#if __cplusplus > 201103L + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + int i = 0; + boost::future<int&> 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<int&> 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<int const&> f = boost::make_ready_future(boost::cref(i)); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::future<int> f = compute(2); + std::cout << f.get() << std::endl; + } + { + std::cout << __FILE__ << " "<< __LINE__ << std::endl; + boost::shared_future<int> f = shared_compute(0); + std::cout << f.get() << std::endl; + } + } + catch (std::exception& ex) + { + std::cout << "ERRORRRRR "<<ex.what() << "" << std::endl; + return 1; + } + catch (...) + { + std::cout << "ERRORRRRR "<<"ERRORRRRR exception thrown" << std::endl; + return 2; + } + return 0; +} diff --git a/src/boost/libs/thread/example/monitor.cpp b/src/boost/libs/thread/example/monitor.cpp new file mode 100644 index 000000000..5c9a74210 --- /dev/null +++ b/src/boost/libs/thread/example/monitor.cpp @@ -0,0 +1,113 @@ +// 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 <vector> +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread_only.hpp> + +namespace { +const int ITERS = 100; +boost::mutex io_mutex; +} // namespace + +template <typename M> +class buffer_t +{ +public: + typedef boost::unique_lock<M> 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<boost::mutex> 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<boost::mutex> lock(io_mutex); + std::cout << "received: " << n << std::endl; + } + } + } + +private: + M mutex; + boost::condition_variable_any cond; + unsigned int p, c, full; + std::vector<int> buf; +}; + +template <typename M> +void do_test(M* dummy=0) +{ + (void)dummy; + typedef buffer_t<M> 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<boost::mutex>(); + do_test<boost::recursive_mutex>(); +} + +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 <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <iostream> + +boost::mutex io_mutex; // The iostreams are not guaranteed to be thread-safe! + +class counter +{ +public: + counter() : count(0) { } + + int increment() { + boost::unique_lock<boost::mutex> scoped_lock(mutex); + return ++count; + } + +private: + boost::mutex mutex; + int count; +}; + +counter c; + +void change_count() +{ + int i = c.increment(); + boost::unique_lock<boost::mutex> 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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#include <boost/thread/externally_locked_stream.hpp> + +void use_cerr(boost::externally_locked_stream<std::ostream> &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<std::ostream> &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<std::ostream> mcerr(std::cerr, terminal_mutex); + externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex); + externally_locked_stream<std::istream> 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<recursive_mutex> 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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#include <boost/thread/ostream_buffer.hpp> + +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<std::ostream> 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<std::ostream> 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<std::ostream> mcout(std::cout); + mcout.stream() << "Enter name: \n"; + } + t1.join(); + t2.join(); + { + ostream_buffer<std::ostream> 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 <boost/thread/thread.hpp> +#include <boost/thread/once.hpp> +#include <cassert> + +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 <boost/config.hpp> + +#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 <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/future.hpp> + +#include <numeric> +#include <algorithm> +#include <functional> +#include <iostream> +#include <vector> + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +template<typename Iterator,typename T> +struct accumulate_block +{ + //typedef T result_type; + T operator()(Iterator first,Iterator last) + { + return std::accumulate(first,last,T()); + } +}; + +template<typename Iterator,typename T> +T parallel_accumulate(Iterator first,Iterator last,T init) +{ + unsigned long const length=static_cast<unsigned long>(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<boost::future<T> > 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<Iterator,T>(), block_start, block_end); + block_start=block_end; + } + T last_result=accumulate_block<Iterator,T>()(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<int> vec; + vec.reserve(s); + for (int i=0; i<s;++i) + vec.push_back(1); + int r = parallel_accumulate(vec.begin(), vec.end(),0); + std::cout << r << 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" +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/example/parallel_quick_sort.cpp b/src/boost/libs/thread/example/parallel_quick_sort.cpp new file mode 100644 index 000000000..c8dc46fae --- /dev/null +++ b/src/boost/libs/thread/example/parallel_quick_sort.cpp @@ -0,0 +1,110 @@ +// 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 <boost/config.hpp> + +#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 <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/future.hpp> +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +#include <numeric> +#include <algorithm> +#include <functional> +#include <iostream> +#include <list> + +template<typename T> +struct sorter +{ + boost::basic_thread_pool pool; + typedef std::list<T> return_type; + + std::list<T> do_sort(std::list<T> chunk_data) + { + if(chunk_data.empty()) + { + return chunk_data; + } + + std::list<T> result; + result.splice(result.begin(),chunk_data, chunk_data.begin()); + T const& partition_val=*result.begin(); + + typename std::list<T>::iterator divide_point= + std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val){return val<partition_val;}); + + std::list<T> new_lower_chunk; + new_lower_chunk.splice(new_lower_chunk.end(), chunk_data, chunk_data.begin(), divide_point); + + boost::future<std::list<T> > new_lower = boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk)); + //boost::future<std::list<T> > new_lower = boost::async<return_type>(pool, &sorter::do_sort, this, std::move(new_lower_chunk)); + + std::list<T> 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<typename T> +std::list<T> parallel_quick_sort(std::list<T>& input) +{ + if(input.empty()) + { + return input; + } + sorter<T> s; + + return s.do_sort(input); +} + + +int main() +{ + try + { + const int s = 101; + std::list<int> lst; + for (int i=0; i<s;++i) + lst.push_back(100-i); + std::list<int> r = parallel_quick_sort(lst); + for (std::list<int>::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 <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/chrono/stopwatches/simple_stopwatch.hpp> + +#include <condition_variable> +#include <future> +#include <limits> +#include <cstdio> +#include <thread> +#include <mutex> +#include <vector> + +//////////////////////////////////////////////////////////////////////////////////////////////// + +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<std::mutex> scoped_lock; + }; + + template <class Types> + 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 <class S> + 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 <class S> + 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 <class Types> + Stopwatch::rep benchmark_ping_pong(unsigned consumer_count) + { + typedef SharedData<Types> S; + + auto best_producer_time = std::numeric_limits<Stopwatch::rep>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + + std::vector<std::thread> 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<S> , &shared_data }; + // Start the producer and wait till it finishes. + std::thread + { producer_thread<S> , &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<StdTypes> (i); + std::printf("BOOST: %d\n", i); + b.boost = benchmark_ping_pong<BoostTypes> (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 <iostream> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/chrono/chrono_io.hpp> + +#include <boost/thread/shared_mutex.hpp> + +using namespace boost; + +shared_mutex mtx; +const int cycles = 10000; + +void shared() +{ + int cycle(0); + while (++cycle < cycles) + { + shared_lock<shared_mutex> lock(mtx); + } +} + +void unique() +{ + int cycle(0); + while (++cycle < cycles) + { + unique_lock<shared_mutex> lock(mtx); + } +} + +int main() +{ + boost::chrono::high_resolution_clock::duration best_time(std::numeric_limits<boost::chrono::high_resolution_clock::duration::rep>::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 <boost/config.hpp> + +#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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#ifdef XXXX +#include <boost/thread/externally_locked_stream.hpp> + typedef boost::externally_locked_stream<std::ostream> the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif +#include <boost/thread/concurrent_queues/sync_queue.hpp> + +void producer(the_ostream & /*mos*/, boost::sync_queue<int> & 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<int> & 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<int> & 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<int> & 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<std::ostream> mcerr(std::cerr, terminal_mutex); + externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex); + externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex); +#else + the_ostream &mcerr = std::cout; + the_ostream &mcout = std::cerr; + //the_istream &mcin = std::cin; +#endif + + sync_queue<int> 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 <boost/config.hpp> + +#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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#ifdef XXXX +#include <boost/thread/externally_locked_stream.hpp> + typedef boost::externally_locked_stream<std::ostream> the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif +#include <boost/thread/concurrent_queues/sync_queue.hpp> +#include <boost/thread/concurrent_queues/queue_adaptor.hpp> +#include <boost/thread/concurrent_queues/queue_views.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits.hpp> + +void producer(the_ostream &/*mos*/, boost::queue_back<int> 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<int> 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<int> 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<int> 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<std::ostream> mcerr(std::cerr, terminal_mutex); + externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex); + externally_locked_stream<std::istream> mcin(std::cin, terminal_mutex); +#else + the_ostream &mcerr = std::cout; + the_ostream &mcout = std::cerr; + //the_istream &mcin = std::cin; +#endif + + queue_adaptor<sync_queue<int> > sbq; + + { + mcout << "begin of main" << std::endl; + scoped_thread<> t11(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq))); + scoped_thread<> t12(boost::thread(producer, boost::ref(mcerr), concurrent::queue_back<int>(sbq))); + scoped_thread<> t2(boost::thread(consumer, boost::ref(mcout), concurrent::queue_front<int>(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 <boost/config.hpp> + +#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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#ifdef XXXX +#include <boost/thread/externally_locked_stream.hpp> + typedef boost::externally_locked_stream<std::ostream> the_ostream; +#else + typedef std::ostream the_ostream; + typedef std::istream the_istream; +#endif + +#include <boost/thread/sync_bounded_queue.hpp> + +void producer(the_ostream &/*mos*/, boost::sync_bounded_queue<int> & 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<int> & 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<int> & 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<int> & 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<std::ostream> mcerr(std::cerr, terminal_mutex); + externally_locked_stream<std::ostream> mcout(std::cout, terminal_mutex); + externally_locked_stream<std::istream> 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<int> 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 <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <iostream> + +class counter +{ +public: + counter() : count(0) { } + + int add(int val) { + boost::unique_lock<boost::recursive_mutex> scoped_lock(mutex); + count += val; + return count; + } + int increment() { + boost::unique_lock<boost::recursive_mutex> 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 <iostream> +#include <boost/thread/scoped_thread.hpp> + +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 <boost/config.hpp> +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/serial_executor.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/executor_adaptor.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> + +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 <boost/config.hpp> +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/serial_executor_cont.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/executor_adaptor.hpp> +#include <boost/thread/executor.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <string> +#include <iostream> + +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 <iostream> +#include <boost/thread/mutex.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/thread_only.hpp> +#if defined BOOST_THREAD_DONT_USE_CHRONO +#include <boost/chrono/chrono_io.hpp> +#endif +#include <cassert> +#include <vector> + +#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<double> 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<mutex_type> lk(a.mut_); +#elif MODE == SHARED + boost::shared_lock<mutex_type> lk(a.mut_); +#else +#error MODE not set +#endif + data_ = a.data_; +} + +A& +A::operator=(const A& a) +{ + if (this != &a) + { + boost::unique_lock<mutex_type> lk1(mut_, boost::defer_lock); +#if MODE == EXCLUSIVE + boost::unique_lock<mutex_type> lk2(a.mut_, boost::defer_lock); +#elif MODE == SHARED + boost::shared_lock<mutex_type> 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<mutex_type> lk1(mut_, boost::defer_lock); +#if MODE == EXCLUSIVE + boost::unique_lock<mutex_type> lk2(x.mut_, boost::defer_lock); + boost::unique_lock<mutex_type> lk3(y.mut_, boost::defer_lock); +#elif MODE == SHARED + boost::shared_lock<mutex_type> lk2(x.mut_, boost::defer_lock); + boost::shared_lock<mutex_type> 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<double> sec; + Clock::time_point t0 = Clock::now(); +#endif + std::vector<boost::thread*> 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 <iostream> +#include <boost/thread/mutex.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/thread_only.hpp> +#include <vector> + +#if defined BOOST_THREAD_USES_CHRONO +#include <boost/chrono/chrono_io.hpp> + + +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<boost::mutex> _(cout_mut()); + std::cout << tag << count << ch; +} + +#elif 0 + +boost::recursive_mutex& +cout_mut() +{ + static boost::recursive_mutex m; + return m; +} + +void print() {} + +template <class A0, class ...Args> +void +print(const A0& a0, const Args& ...args) +{ + boost::lock_guard<boost::recursive_mutex> _(cout_mut()); + std::cout << a0; + print(args...); +} + +#else + +template <class A0, class A1, class A2> +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<mutex_type> SharedLock; + typedef boost::upgrade_lock<mutex_type> UpgradeLock; + typedef boost::unique_lock<mutex_type> Lock; + + mutable mutex_type mut_; + std::vector<double> 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<upgrade_mutex> ul(mut); + shared_lock<upgrade_mutex> sl; + sl = BOOST_THREAD_MAKE_RV_REF(shared_lock<upgrade_mutex>(boost::move(ul))); +} + +int main() +{ + std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; + typedef boost::chrono::high_resolution_clock Clock; + typedef boost::chrono::duration<double> 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 <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <iostream> +#include <time.h> + +namespace +{ +boost::mutex iomx; +} // namespace + +class canteen +{ +public: + canteen() : m_chickens(0) { } + + void get(int id) + { + boost::unique_lock<boost::mutex> lock(m_mutex); + while (m_chickens == 0) + { + { + boost::unique_lock<boost::mutex> lk(iomx); + std::cout << "(" << clock() << ") Phil" << id << + ": wot, no chickens? I'll WAIT ..." << std::endl; + } + m_condition.wait(lock); + } + { + boost::unique_lock<boost::mutex> lk(iomx); + std::cout << "(" << clock() << ") Phil" << id << + ": those chickens look good ... one please ..." << std::endl; + } + m_chickens--; + } + void put(int value) + { + boost::unique_lock<boost::mutex> lock(m_mutex); + { + boost::unique_lock<boost::mutex> 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<boost::mutex> 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<boost::mutex> lock(iomx); + std::cout << "(" << clock() << ") Chef: starting ..." << std::endl; + } + for (;;) + { + { + boost::unique_lock<boost::mutex> 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<boost::mutex> 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<boost::mutex> 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<boost::mutex> lk(iomx); + std::cout << "(" << clock() << ") Phil" << m_id + << ": gotta eat ..." << std::endl; + } + g_canteen.get(m_id); + { + boost::unique_lock<boost::mutex> lk(iomx); + std::cout << "(" << clock() << ") Phil" << m_id + << ": mmm ... that's good ..." << std::endl; + } + } + } + static void do_thread(void* param) { + static_cast<phil*>(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 <iostream> +#include <boost/thread/scoped_thread.hpp> +#include <thread> +#include <cassert> + +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<boost::join_if_joinable, std::thread>; +using scoped_thread = boost::scoped_thread<boost::join_if_joinable, std::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 <iostream> +#include <string> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/thread_guard.hpp> +#include <thread> + +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<boost::join_if_joinable, std::thread>; + + +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 <boost/thread/mutex.hpp> +#include <boost/thread/lock_traits.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <iostream> + + +BOOST_STATIC_ASSERT(boost::is_strict_lock<boost::strict_lock<boost::mutex> >::value); +BOOST_CONCEPT_ASSERT(( boost::BasicLockable<boost::mutex> )); +BOOST_CONCEPT_ASSERT(( boost::StrictLock<boost::strict_lock<boost::mutex> > )); + +int main() +{ + { + boost::mutex mtx; + boost::strict_lock<boost::mutex> lk(mtx); + std::cout << __FILE__ << std::endl; + } + { + boost::timed_mutex mtx; + boost::unique_lock<boost::timed_mutex> lk(mtx); + boost::nested_strict_lock<boost::unique_lock<boost::timed_mutex> > nlk(lk); + std::cout << __FILE__ << std::endl; + } + { + boost::mutex mtx; + boost::unique_lock<boost::mutex> lk(mtx, boost::defer_lock); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > 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 <iostream> +#include <string> +#include <boost/thread/synchronized_value.hpp> + +//class SafePerson { +//public: +// std::string GetName() const { +// const_unique_access<std::string> name(nameGuard); +// return *name; +// } +// void SetName(const std::string& newName) { +// unique_access<std::string> name(nameGuard); +// *name = newName; +// } +//private: +// unique_access_guard<std::string> nameGuard; +//}; + +class SafePerson { +public: + std::string GetName() const { + return *name; + } + void SetName(const std::string& newName) { + *name = newName; + } + +private: + boost::synchronized_value<std::string> 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> Person_ts; + + +//class SafeMemberPerson { +//public: +// SafeMemberPerson(unsigned int age) : +// memberGuard(age) +// { } +// std::string GetName() const { +// const_unique_access<Member> member(memberGuard); +// return member->name; +// } +// void SetName(const std::string& newName) { +// unique_access<Member> member(memberGuard); +// member->name = newName; +// } +//private: +// struct Member +// { +// Member(unsigned int age) : +// age(age) +// { } +// std::string name; +// unsigned int age; +// }; +// unique_access_guard<Member> 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> 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> Person2_ts; + +//=================== + +//class HelperPerson { +//public: +// HelperPerson(unsigned int age) : +// memberGuard(age) +// { } +// std::string GetName() const { +// const_unique_access<Member> member(memberGuard); +// Invariant(member); +// return member->name; +// } +// void SetName(const std::string& newName) { +// unique_access<Member> member(memberGuard); +// Invariant(member); +// member->name = newName; +// } +//private: +// void Invariant(const_unique_access<Member>& 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<Member> 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<Member> 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<Member> 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<Member> & mbr) const + { + if (mbr->age < 1) throw std::runtime_error("Age cannot be negative"); + } + boost::synchronized_value<Member> 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> 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<Person3> lk1 = p1.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr<Person3> lk2 = p2.unique_synchronize(boost::defer_lock); + boost::unique_lock_ptr<Person3> 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 <iostream> +#include <string> +#include <boost/thread/synchronized_value.hpp> + + void addTrailingSlashIfMissing(boost::synchronized_value<std::string> & path) + { + boost::strict_lock_ptr<std::string> u=path.synchronize(); + + if(u->empty() || (*u->rbegin()!='/')) + { + *u+='/'; + } + } + +void f(const boost::synchronized_value<int> &v) { + std::cout<<"v="<<*v<<std::endl; +} + +void g(const boost::const_strict_lock_ptr<int> &v) { + std::cout<<"v="<<*v<<std::endl; +} + +bool checkIfMissingTrailingSlash(boost::synchronized_value<std::string> & path) +{ + boost::strict_lock_ptr<std::string> u=path.synchronize(); + + return (u->empty() || (*u->rbegin()!='/')); +} + +int main() +{ + { + boost::synchronized_value<int> v1; + *v1=42; + std::cout<<"v1="<<*v1<<std::endl; + f(v1); + int i=*v1; + std::cout<<"i="<<i<<std::endl; + + { + boost::strict_lock_ptr<int> u=v1.synchronize(); + + *u+=43; + std::cout<<"v1="<<*u<<std::endl; + g(u); + } + boost::synchronized_value<int> v2(2); + std::cout<<"v2="<<*v2<<std::endl; + v2 = 3; + std::cout<<"v2="<<*v2<<std::endl; + + boost::synchronized_value<int> v3(v2); + std::cout<<"v3="<<*v3<<std::endl; + v3 = v1; + std::cout<<"v3="<<*v3<<std::endl; + + std::cout<<"v2="<<*v3<<std::endl; + std::cout<<"v3="<<*v3<<std::endl; + swap(v3,v2); + v1.swap(v2); + std::cout<<"v3="<<*v3<<std::endl; + } + { + boost::synchronized_value<std::string> s; + addTrailingSlashIfMissing(s); + std::cout<<"s="<<std::string(*s)<<std::endl; + } + { + boost::synchronized_value<std::string> s; + s->append("foo/"); + s.synchronize()->append("foo"); + addTrailingSlashIfMissing(s); + std::cout<<"s="<<std::string(*s)<<std::endl; + } + { + boost::synchronized_value<std::string> s; + s = std::string("foo/"); + std::cout<<"ss="<< s << std::endl; + } + { + boost::synchronized_value<std::string> s; + s = "foo/"; + std::cout<<"ss="<< s << std::endl; + } + { + boost::synchronized_value<std::string> s1("a"); + boost::synchronized_value<std::string> s2; + s2=s1; + std::cout<<"s1="<< s1 << std::endl; + std::cout<<"s2="<< s2 << std::endl; + } + { + boost::synchronized_value<std::string> s1("a"); + boost::synchronized_value<std::string> 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<std::string> sts("a"); + std::string s(sts); + std::cout<<"ssts="<< s << std::endl; + } +#endif + { + boost::synchronized_value<int> s1(1); + boost::synchronized_value<int> 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<int> s1(1); + boost::synchronized_value<int> s2(2); + BOOST_ASSERT(s1!=s2); + BOOST_ASSERT(s1!=2); + BOOST_ASSERT(2!=s1); + } + { + boost::synchronized_value<int> s1(1); + boost::synchronized_value<int> s2(2); + BOOST_ASSERT(s1<s2); + BOOST_ASSERT(s1<=s2); + BOOST_ASSERT(s2>s1); + 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 <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <iostream> + +#if defined(BOOST_HAS_WINTHREADS) +# include <windows.h> +# include <process.h> +#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<boost::mutex> 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<boost::mutex> lock(mutex); + std::cout << "---Noise ON..." << std::endl; + } + + for (int i = 0; i < 10; ++i) + cond.notify_all(); + + { + boost::unique_lock<boost::mutex> 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 <boost/config.hpp> +#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 <boost/thread/caller_context.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/generic_executor_ref.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <string> +#include <iostream> + +#include <boost/thread/caller_context.hpp> + +struct current_executor_state_type { + boost::shared_ptr<boost::generic_executor_ref> current_executor_ptr; + + template <class Executor> + void set_current_executor(Executor& ex) + { + current_executor_ptr = boost::make_shared<boost::generic_executor_ref>(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 <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <iostream> + +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 <boost/thread/thread.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; +boost::mutex mutex; + +void increment_count() +{ + boost::unique_lock<boost::mutex> lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +boost::thread_group threads2; +boost::thread* th2 = 0; + +void increment_count_2() +{ + boost::unique_lock<boost::mutex> 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<boost::mutex> 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 <iostream> +#include <string> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/thread_guard.hpp> + +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 <boost/config.hpp> + +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/assert.hpp> +#include <string> + +#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() << " <MAIN" << BOOST_THREAD_END_LOG; + { + try + { + boost::basic_thread_pool tp; + submit_some(tp); + } + 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 + << boost::this_thread::get_id() << "MAIN>" << 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 <boost/thread/thread.hpp> +#include <boost/thread/tss.hpp> +#include <cassert> + +boost::thread_specific_ptr<int> 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 <boost/config.hpp> + +#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 <boost/thread/detail/log.hpp> +#include <boost/thread/executors/loop_executor.hpp> +#include <boost/assert.hpp> +#include <boost/thread/thread_only.hpp> +#include <string> + +#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() << " <MAIN" << BOOST_THREAD_END_LOG; + { + try + { + boost::loop_executor tp; + submit_some(tp); + tp.run_queued_closures(); + submit_some(tp); + tp.run_queued_closures(); + } + 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 + << boost::this_thread::get_id() << "MAIN>" << 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 <iostream> // std::cout +#include <boost/thread/scoped_thread.hpp> +#include <boost/thread/with_lock_guard.hpp> + +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 <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> + +int main() +{ + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC_); + xt.sec += 1; + boost::thread::sleep(xt); // Sleep for 1 second +} diff --git a/src/boost/libs/thread/index.html b/src/boost/libs/thread/index.html new file mode 100644 index 000000000..f54e21e2f --- /dev/null +++ b/src/boost/libs/thread/index.html @@ -0,0 +1,13 @@ +<!-- Copyright (c) 2002-2003 William E. Kempf. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<html> +<head> +<meta http-equiv="refresh" content="0; URL=doc/index.html"> +</head> +<body> +Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a> +</body> +</html> diff --git a/src/boost/libs/thread/meta/libraries.json b/src/boost/libs/thread/meta/libraries.json new file mode 100644 index 000000000..d225f2917 --- /dev/null +++ b/src/boost/libs/thread/meta/libraries.json @@ -0,0 +1,19 @@ +[ + { + "key": "thread", + "name": "Thread", + "authors": [ + "Anthony Williams", + "Vicente J. Botet Escriba" + ], + "maintainers": [ + "Vicente J. Botet Escriba <vicente.botet -at- wanadoo.fr>" + ], + "description": + "Portable C++ multi-threading. C++03, C++11, C++14, C++17.", + "std": [ "proposal" ], + "category": [ + "Concurrent", "System" + ] + } +] diff --git a/src/boost/libs/thread/src/future.cpp b/src/boost/libs/thread/src/future.cpp new file mode 100644 index 000000000..a477e709a --- /dev/null +++ b/src/boost/libs/thread/src/future.cpp @@ -0,0 +1,64 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Use, modification and distribution are subject to 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 <boost/thread/detail/config.hpp> + +#ifndef BOOST_NO_EXCEPTIONS + +#include <boost/thread/futures/future_error_code.hpp> +#include <string> + +namespace boost +{ + + namespace thread_detail + { + + class future_error_category : + public boost::system::error_category + { + public: + virtual const char* name() const BOOST_NOEXCEPT; + virtual std::string message(int ev) const; + }; + + const char* + future_error_category::name() const BOOST_NOEXCEPT + { + return "future"; + } + + std::string + future_error_category::message(int ev) const + { + switch (BOOST_SCOPED_ENUM_NATIVE(future_errc)(ev)) + { + case future_errc::broken_promise: + return std::string("The associated promise has been destructed prior " + "to the associated state becoming ready."); + case future_errc::future_already_retrieved: + return std::string("The future has already been retrieved from " + "the promise or packaged_task."); + case future_errc::promise_already_satisfied: + return std::string("The state of the promise has already been set."); + case future_errc::no_state: + return std::string("Operation not permitted on an object without " + "an associated state."); + } + return std::string("unspecified future_errc value\n"); + } + future_error_category future_error_category_var; + } + + BOOST_THREAD_DECL + const system::error_category& + future_category() BOOST_NOEXCEPT + { + return thread_detail::future_error_category_var; + } + +} +#endif + diff --git a/src/boost/libs/thread/src/pthread/once.cpp b/src/boost/libs/thread/src/pthread/once.cpp new file mode 100644 index 000000000..3de1fe4b0 --- /dev/null +++ b/src/boost/libs/thread/src/pthread/once.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> +#ifdef BOOST_THREAD_ONCE_ATOMIC +#include "./once_atomic.cpp" +#else +#define __STDC_CONSTANT_MACROS +#include <boost/thread/once.hpp> +#include <boost/assert.hpp> +#include <boost/throw_exception.hpp> +#include <pthread.h> +#include <stdlib.h> +#include <memory> +#include <string.h> // memcmp. +namespace boost +{ + namespace thread_detail + { + BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; + BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; + + namespace + { + pthread_key_t epoch_tss_key; + pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; + + extern "C" + { + static void delete_epoch_tss_data(void* data) + { + free(data); + } + + static void create_epoch_tss_key() + { + BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); + } + } + +#if defined BOOST_THREAD_PATCH + const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT; + struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t + { + delete_epoch_tss_key_on_dlclose_t() + { + } + ~delete_epoch_tss_key_on_dlclose_t() + { + if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t))) + { + void* data = pthread_getspecific(epoch_tss_key); + if (data) + delete_epoch_tss_data(data); + pthread_key_delete(epoch_tss_key); + } + } + }; + delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose; +#endif + } + + uintmax_atomic_t& get_once_per_thread_epoch() + { + BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); + void* data=pthread_getspecific(epoch_tss_key); + if(!data) + { + data=malloc(sizeof(thread_detail::uintmax_atomic_t)); + if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); + BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); + *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + } + return *static_cast<thread_detail::uintmax_atomic_t*>(data); + } + } + +} +#endif // diff --git a/src/boost/libs/thread/src/pthread/once_atomic.cpp b/src/boost/libs/thread/src/pthread/once_atomic.cpp new file mode 100644 index 000000000..69f5be809 --- /dev/null +++ b/src/boost/libs/thread/src/pthread/once_atomic.cpp @@ -0,0 +1,91 @@ +// (C) Copyright 2013 Andrey Semashev +// (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) + +//#define __STDC_CONSTANT_MACROS +#include <boost/thread/detail/config.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/pthread/pthread_helpers.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/atomic.hpp> +#include <boost/memory_order.hpp> +#include <pthread.h> + +namespace boost +{ + namespace thread_detail + { + + enum flag_states + { + uninitialized, in_progress, initialized + }; + + +#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11 + BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type) == sizeof(atomic_type), "Boost.Thread: unsupported platform"); +#endif + + static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + if (f.load(memory_order_acquire) != initialized) + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + if (f.load(memory_order_acquire) != initialized) + { + for (;;) + { + atomic_int_type expected = uninitialized; + if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire)) + { + // We have set the flag to in_progress + return true; + } + else if (expected == initialized) + { + // Another thread managed to complete the initialization + return false; + } + else + { + // Wait until the initialization is complete + //pthread::pthread_mutex_scoped_lock lk(&once_mutex); + BOOST_VERIFY(!posix::pthread_cond_wait(&once_cv, &once_mutex)); + } + } + } + } + return false; + } + + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(initialized, memory_order_release); + } + BOOST_VERIFY(!posix::pthread_cond_broadcast(&once_cv)); + } + + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(uninitialized, memory_order_release); + } + BOOST_VERIFY(!posix::pthread_cond_broadcast(&once_cv)); + } + + } // namespace thread_detail + +} // namespace boost diff --git a/src/boost/libs/thread/src/pthread/thread.cpp b/src/boost/libs/thread/src/pthread/thread.cpp new file mode 100644 index 000000000..c17aca2cc --- /dev/null +++ b/src/boost/libs/thread/src/pthread/thread.cpp @@ -0,0 +1,801 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// (C) Copyright 2011-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 <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> +#if defined BOOST_THREAD_USES_DATETIME +#include <boost/thread/xtime.hpp> +#endif +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/pthread/pthread_helpers.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> + +#ifdef __GLIBC__ +#include <sys/sysinfo.h> +#elif defined(__APPLE__) || defined(__FreeBSD__) +#include <sys/types.h> +#include <sys/sysctl.h> +#elif defined BOOST_HAS_UNISTD_H +#include <unistd.h> +#endif + +#if defined(__VXWORKS__) +#include <vxCpuLib.h> +#endif + +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/lexical_cast.hpp> + +#include <fstream> +#include <string> +#include <set> +#include <vector> +#include <string.h> // memcmp. + +namespace boost +{ + namespace detail + { + thread_data_base::~thread_data_base() + { + for (notify_list_t::iterator i = notify.begin(), e = notify.end(); + i != e; ++i) + { + i->second->unlock(); + i->first->notify_all(); + } +//#ifndef BOOST_NO_EXCEPTIONS + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->notify_deferred(); + } +//#endif + } + + struct thread_exit_callback_node + { + boost::detail::thread_exit_function_base* func; + thread_exit_callback_node* next; + + thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, + thread_exit_callback_node* next_): + func(func_),next(next_) + {} + }; + + namespace + { +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + boost::once_flag current_thread_tls_init_flag; +#else + boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; +#endif + pthread_key_t current_thread_tls_key; + + extern "C" + { + static void tls_destructor(void* data) + { + //boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data); + boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this(); + + if(thread_info) + { + while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks) + { + + while(thread_info->thread_exit_callbacks) + { + detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks; + thread_info->thread_exit_callbacks=current_node->next; + if(current_node->func) + { + (*current_node->func)(); + delete current_node->func; + } + delete current_node; + } + while (!thread_info->tss_data.empty()) + { + std::map<void const*,detail::tss_data_node>::iterator current + = thread_info->tss_data.begin(); + if(current->second.func && (current->second.value!=0)) + { + (*current->second.caller)(current->second.func,current->second.value); + } + thread_info->tss_data.erase(current); + } + } + thread_info->self.reset(); + } + } + } + +#if defined BOOST_THREAD_PATCH + struct delete_current_thread_tls_key_on_dlclose_t + { + delete_current_thread_tls_key_on_dlclose_t() + { + } + ~delete_current_thread_tls_key_on_dlclose_t() + { + const boost::once_flag uninitialized = BOOST_ONCE_INIT; + if (memcmp(¤t_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag))) + { + void* data = pthread_getspecific(current_thread_tls_key); + if (data) + tls_destructor(data); + pthread_key_delete(current_thread_tls_key); + } + } + }; + delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose; +#endif + void create_current_thread_tls_key() + { + BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor)); + } + } + + boost::detail::thread_data_base* get_current_thread_data() + { + boost::call_once(current_thread_tls_init_flag,&create_current_thread_tls_key); + return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key); + } + + void set_current_thread_data(detail::thread_data_base* new_data) + { + boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); + BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); + } + } + + namespace + { + extern "C" + { + static void* thread_proxy(void* param) + { + //boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; + boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this(); + thread_info->self.reset(); + detail::set_current_thread_data(thread_info.get()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_TRY + { +#endif + thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + + } + BOOST_CATCH (thread_interrupted const&) + { + } +// Removed as it stops the debugger identifying the cause of the exception +// Unhandled exceptions still cause the application to terminate +// BOOST_CATCH(...) +// { +// throw; +// +// std::terminate(); +// } + BOOST_CATCH_END +#endif + detail::tls_destructor(thread_info.get()); + detail::set_current_thread_data(0); + boost::lock_guard<boost::mutex> lock(thread_info->data_mutex); + thread_info->done=true; + thread_info->done_condition.notify_all(); + + return 0; + } + } + } + namespace detail + { + struct externally_launched_thread: + detail::thread_data_base + { + externally_launched_thread() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + interrupt_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); +//#ifndef BOOST_NO_EXCEPTIONS + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); +//#endif + } + void run() + {} + void notify_all_at_thread_exit(condition_variable*, mutex*) + {} + + private: + externally_launched_thread(externally_launched_thread&); + void operator=(externally_launched_thread&); + }; + + thread_data_base* make_external_thread_data() + { + thread_data_base* const me(detail::heap_new<externally_launched_thread>()); + me->self.reset(me); + set_current_thread_data(me); + return me; + } + + + thread_data_base* get_or_make_current_thread_data() + { + thread_data_base* current_thread_data(get_current_thread_data()); + if(!current_thread_data) + { + current_thread_data=make_external_thread_data(); + } + return current_thread_data; + } + + } + + + thread::thread() BOOST_NOEXCEPT + {} + + bool thread::start_thread_noexcept() + { + thread_info->self=thread_info; + int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get()); + if (res != 0) + { + thread_info->self.reset(); + return false; + } + return true; + } + + bool thread::start_thread_noexcept(const attributes& attr) + { + thread_info->self=thread_info; + const attributes::native_handle_type* h = attr.native_handle(); + int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get()); + if (res != 0) + { + thread_info->self.reset(); + return false; + } + int detached_state; + res = pthread_attr_getdetachstate(h, &detached_state); + if (res != 0) + { + thread_info->self.reset(); + return false; + } + if (PTHREAD_CREATE_DETACHED==detached_state) + { + detail::thread_data_ptr local_thread_info; + thread_info.swap(local_thread_info); + + if(local_thread_info) + { + //lock_guard<mutex> lock(local_thread_info->data_mutex); + if(!local_thread_info->join_started) + { + //BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle)); + local_thread_info->join_started=true; + local_thread_info->joined=true; + } + } + } + return true; + } + + + + detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const + { + return thread_info; + } + + bool thread::join_noexcept() + { + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + bool do_join=false; + + { + unique_lock<mutex> lock(local_thread_info->data_mutex); + while(!local_thread_info->done) + { + local_thread_info->done_condition.wait(lock); + } + do_join=!local_thread_info->join_started; + + if(do_join) + { + local_thread_info->join_started=true; + } + else + { + while(!local_thread_info->joined) + { + local_thread_info->done_condition.wait(lock); + } + } + } + if(do_join) + { + void* result=0; + BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); + lock_guard<mutex> lock(local_thread_info->data_mutex); + local_thread_info->joined=true; + local_thread_info->done_condition.notify_all(); + } + + if(thread_info==local_thread_info) + { + thread_info.reset(); + } + return true; + } + else + { + return false; + } + } + + bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res) + { + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + bool do_join=false; + + { + unique_lock<mutex> lock(local_thread_info->data_mutex); + while(!local_thread_info->done) + { + if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) break; // timeout occurred + } + if(!local_thread_info->done) + { + res=false; + return true; + } + do_join=!local_thread_info->join_started; + + if(do_join) + { + local_thread_info->join_started=true; + } + else + { + while(!local_thread_info->joined) + { + local_thread_info->done_condition.wait(lock); + } + } + } + if(do_join) + { + void* result=0; + BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result)); + lock_guard<mutex> lock(local_thread_info->data_mutex); + local_thread_info->joined=true; + local_thread_info->done_condition.notify_all(); + } + + if(thread_info==local_thread_info) + { + thread_info.reset(); + } + res=true; + return true; + } + else + { + return false; + } + } + + bool thread::joinable() const BOOST_NOEXCEPT + { + return (get_thread_info)()?true:false; + } + + + void thread::detach() + { + detail::thread_data_ptr local_thread_info; + thread_info.swap(local_thread_info); + + if(local_thread_info) + { + lock_guard<mutex> lock(local_thread_info->data_mutex); + if(!local_thread_info->join_started) + { + BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle)); + local_thread_info->join_started=true; + local_thread_info->joined=true; + } + } + } + + namespace this_thread + { + namespace no_interruption_point + { + namespace hidden + { + void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts) + { + if (ts > detail::platform_duration::zero()) + { + // Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point + // namespace because they do not provide an interruption point. + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + # if defined(__IBMCPP__) || defined(_AIX) + BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts.getTs()))); + # else + BOOST_VERIFY(!pthread_delay_np(&ts.getTs())); + # endif + # elif defined(BOOST_HAS_NANOSLEEP) + nanosleep(&ts.getTs(), 0); + # else + // This should never be reached due to BOOST_THREAD_SLEEP_FOR_IS_STEADY + # endif + } + } + } + } + + void yield() BOOST_NOEXCEPT + { +# if defined(BOOST_HAS_SCHED_YIELD) + BOOST_VERIFY(!sched_yield()); +# elif defined(BOOST_HAS_PTHREAD_YIELD) + BOOST_VERIFY(!pthread_yield()); +//# elif defined BOOST_THREAD_USES_DATETIME +// ::boost::xtime xt; +// xtime_get(&xt, TIME_UTC_); +// sleep(xt); +// sleep_for(chrono::milliseconds(0)); +# else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_until(lock, detail::internal_platform_clock::now()); +# endif + } + } + unsigned thread::hardware_concurrency() BOOST_NOEXCEPT + { +#if defined(PTW32_VERSION) || defined(__hpux) + return pthread_num_processors_np(); +#elif defined(__APPLE__) || defined(__FreeBSD__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count; +#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) + int const count=sysconf(_SC_NPROCESSORS_ONLN); + return (count>0)?count:0; +#elif defined(__VXWORKS__) + cpuset_t set = ::vxCpuEnabledGet(); + #ifdef __DCC__ + int i; + for( i = 0; set; ++i) + { + set &= set -1; + } + return(i); + #else + return (__builtin_popcount(set) ); + #endif +#elif defined(__GLIBC__) + return get_nprocs(); +#else + return 0; +#endif + } + + unsigned thread::physical_concurrency() BOOST_NOEXCEPT + { +#ifdef __linux__ + try { + using namespace std; + + ifstream proc_cpuinfo ("/proc/cpuinfo"); + + const string physical_id("physical id"), core_id("core id"); + + typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id] + + std::set<core_entry> cores; + + core_entry current_core_entry; + + string line; + while ( getline(proc_cpuinfo, line) ) { + if (line.empty()) + continue; + + vector<string> key_val(2); + boost::split(key_val, line, boost::is_any_of(":")); + + if (key_val.size() != 2) + return hardware_concurrency(); + + string key = key_val[0]; + string value = key_val[1]; + boost::trim(key); + boost::trim(value); + + if (key == physical_id) { + current_core_entry.first = boost::lexical_cast<unsigned>(value); + continue; + } + + if (key == core_id) { + current_core_entry.second = boost::lexical_cast<unsigned>(value); + cores.insert(current_core_entry); + continue; + } + } + // Fall back to hardware_concurrency() in case + // /proc/cpuinfo is formatted differently than we expect. + return cores.size() != 0 ? cores.size() : hardware_concurrency(); + } catch(...) { + return hardware_concurrency(); + } +#elif defined(__APPLE__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count; +#else + return hardware_concurrency(); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void thread::interrupt() + { + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + local_thread_info->interrupt_requested=true; + if(local_thread_info->current_cond) + { + boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex); + BOOST_VERIFY(!posix::pthread_cond_broadcast(local_thread_info->current_cond)); + } + } + } + + bool thread::interruption_requested() const BOOST_NOEXCEPT + { + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + return local_thread_info->interrupt_requested; + } + else + { + return false; + } + } +#endif + + thread::native_handle_type thread::native_handle() + { + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + lock_guard<mutex> lk(local_thread_info->data_mutex); + return local_thread_info->thread_handle; + } + else + { + return pthread_t(); + } + } + + + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + namespace this_thread + { + void interruption_point() + { +#ifndef BOOST_NO_EXCEPTIONS + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + if(thread_info && thread_info->interrupt_enabled) + { + lock_guard<mutex> lg(thread_info->data_mutex); + if(thread_info->interrupt_requested) + { + thread_info->interrupt_requested=false; + throw thread_interrupted(); + } + } +#endif + } + + bool interruption_enabled() BOOST_NOEXCEPT + { + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + return thread_info && thread_info->interrupt_enabled; + } + + bool interruption_requested() BOOST_NOEXCEPT + { + boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + if(!thread_info) + { + return false; + } + else + { + lock_guard<mutex> lg(thread_info->data_mutex); + return thread_info->interrupt_requested; + } + } + + disable_interruption::disable_interruption() BOOST_NOEXCEPT: + interruption_was_enabled(interruption_enabled()) + { + if(interruption_was_enabled) + { + detail::get_current_thread_data()->interrupt_enabled=false; + } + } + + disable_interruption::~disable_interruption() BOOST_NOEXCEPT + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled; + } + } + + restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT + { + if(d.interruption_was_enabled) + { + detail::get_current_thread_data()->interrupt_enabled=true; + } + } + + restore_interruption::~restore_interruption() BOOST_NOEXCEPT + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interrupt_enabled=false; + } + } + } +#endif + + namespace detail + { + void add_thread_exit_function(thread_exit_function_base* func) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + thread_exit_callback_node* const new_node= + heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks); + current_thread_data->thread_exit_callbacks=new_node; + } + + tss_data_node* find_tss_data(void const* key) + { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + std::map<void const*,tss_data_node>::iterator current_node= + current_thread_data->tss_data.find(key); + if(current_node!=current_thread_data->tss_data.end()) + { + return ¤t_node->second; + } + } + return 0; + } + + void* get_tss_data(void const* key) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + return current_node->value; + } + return 0; + } + + void add_new_tss_node(void const* key, + detail::tss_data_node::cleanup_caller_t caller, + detail::tss_data_node::cleanup_func_t func, + void* tss_data) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(caller,func,tss_data))); + } + + void erase_tss_node(void const* key) + { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->tss_data.erase(key); + } + } + + void set_tss_data(void const* key, + detail::tss_data_node::cleanup_caller_t caller, + detail::tss_data_node::cleanup_func_t func, + void* tss_data,bool cleanup_existing) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + if(cleanup_existing && current_node->func && (current_node->value!=0)) + { + (*current_node->caller)(current_node->func,current_node->value); + } + if(func || (tss_data!=0)) + { + current_node->caller=caller; + current_node->func=func; + current_node->value=tss_data; + } + else + { + erase_tss_node(key); + } + } + else if(func || (tss_data!=0)) + { + add_new_tss_node(key,caller,func,tss_data); + } + } + } + + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); + } + } + +//#ifndef BOOST_NO_EXCEPTIONS +namespace detail { + + void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->make_ready_at_thread_exit(as); + } + } +} +//#endif + + +} diff --git a/src/boost/libs/thread/src/tss_null.cpp b/src/boost/libs/thread/src/tss_null.cpp new file mode 100644 index 000000000..e5e815121 --- /dev/null +++ b/src/boost/libs/thread/src/tss_null.cpp @@ -0,0 +1,38 @@ +// (C) Copyright Michael Glassford 2004. +// (C) Copyright 2007 Anthony Williams +// Use, modification and distribution are subject to 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 <boost/thread/detail/config.hpp> + +#if defined(BOOST_THREAD_WIN32) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE)) + +namespace boost +{ + /* + This file is a "null" implementation of tss cleanup; it's + purpose is to to eliminate link errors in cases + where it is known that tss cleanup is not needed. + */ + + void tss_cleanup_implemented(void) + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } + +} + +#endif //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER) diff --git a/src/boost/libs/thread/src/win32/thread.cpp b/src/boost/libs/thread/src/win32/thread.cpp new file mode 100644 index 000000000..e1ae050bd --- /dev/null +++ b/src/boost/libs/thread/src/win32/thread.cpp @@ -0,0 +1,980 @@ +// 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) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins +// (C) Copyright 2011-2018 Vicente J. Botet Escriba + +//#define BOOST_THREAD_VERSION 3 + +#include <boost/winapi/config.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/tss.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/detail/tss_hooks.hpp> +#include <boost/thread/future.hpp> +#include <boost/assert.hpp> +#include <boost/cstdint.hpp> +#if defined BOOST_THREAD_USES_DATETIME +#include <boost/date_time/posix_time/conversion.hpp> +#include <boost/thread/thread_time.hpp> +#endif +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <memory> +#include <algorithm> +#ifndef UNDER_CE +#include <process.h> +#endif +#include <stdio.h> +#include <windows.h> +#include <boost/predef/platform.h> + +#if BOOST_PLAT_WINDOWS_RUNTIME +#include <mutex> +#include <atomic> +#include <Activation.h> +#include <wrl\client.h> +#include <wrl\event.h> +#include <wrl\wrappers\corewrappers.h> +#include <wrl\ftm.h> +#include <windows.system.threading.h> +#pragma comment(lib, "runtimeobject.lib") +#endif + +namespace boost +{ + namespace detail + { + thread_data_base::~thread_data_base() + { + for (notify_list_t::iterator i = notify.begin(), e = notify.end(); + i != e; ++i) + { + i->second->unlock(); + i->first->notify_all(); + } +//#ifndef BOOST_NO_EXCEPTIONS + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->notify_deferred(); + } +//#endif + } + } + + namespace + { +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + boost::once_flag current_thread_tls_init_flag; +#else + boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT; +#endif +#if defined(UNDER_CE) + // Windows CE does not define the TLS_OUT_OF_INDEXES constant. +#define TLS_OUT_OF_INDEXES 0xFFFFFFFF +#endif +#if !BOOST_PLAT_WINDOWS_RUNTIME + DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES; +#else + __declspec(thread) boost::detail::thread_data_base* current_thread_data_base; +#endif + + void create_current_thread_tls_key() + { + tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in +#if !BOOST_PLAT_WINDOWS_RUNTIME + current_thread_tls_key=TlsAlloc(); + BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES); +#endif + } + + void cleanup_tls_key() + { +#if !BOOST_PLAT_WINDOWS_RUNTIME + if(current_thread_tls_key!=TLS_OUT_OF_INDEXES) + { + TlsFree(current_thread_tls_key); + current_thread_tls_key=TLS_OUT_OF_INDEXES; + } +#endif + } + + void set_current_thread_data(detail::thread_data_base* new_data) + { + boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); +#if BOOST_PLAT_WINDOWS_RUNTIME + current_thread_data_base = new_data; +#else + if (current_thread_tls_key != TLS_OUT_OF_INDEXES) + { + BOOST_VERIFY(TlsSetValue(current_thread_tls_key, new_data)); + } + else + { + BOOST_VERIFY(false); + //boost::throw_exception(thread_resource_error()); + } +#endif + } + } + + namespace detail + { + thread_data_base* get_current_thread_data() + { +#if BOOST_PLAT_WINDOWS_RUNTIME + return current_thread_data_base; +#else + if (current_thread_tls_key == TLS_OUT_OF_INDEXES) + { + return 0; + } + return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); +#endif + } + } + + namespace + { +#ifndef BOOST_HAS_THREADEX +// Windows CE doesn't define _beginthreadex + + struct ThreadProxyData + { + typedef unsigned (__stdcall* func)(void*); + func start_address_; + void* arglist_; + ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {} + }; + + DWORD WINAPI ThreadProxy(LPVOID args) + { + boost::csbl::unique_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args)); + DWORD ret=data->start_address_(data->arglist_); + return ret; + } + + inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*), + void* arglist, unsigned initflag, unsigned* thrdaddr) + { + DWORD threadID; + ThreadProxyData* data = new ThreadProxyData(start_address,arglist); + HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy, + data,initflag,&threadID); + if (hthread==0) { + delete data; + return 0; + } + *thrdaddr=threadID; + return reinterpret_cast<uintptr_t const>(hthread); + } + +#endif + + } + + namespace detail + { + struct thread_exit_callback_node + { + boost::detail::thread_exit_function_base* func; + thread_exit_callback_node* next; + + thread_exit_callback_node(boost::detail::thread_exit_function_base* func_, + thread_exit_callback_node* next_): + func(func_),next(next_) + {} + }; + + } + +#if BOOST_PLAT_WINDOWS_RUNTIME + namespace detail + { + std::atomic_uint threadCount; + + bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId) + { + Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory; + HRESULT hr = ::Windows::Foundation::GetActivationFactory( + Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), + &threadPoolFactory); + if (hr != S_OK) + { + return false; + } + + // Create event for tracking work item completion. + *thrdId = ++threadCount; + handle completionHandle = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS); + if (!completionHandle) + { + return false; + } + m_completionHandle = completionHandle; + + // Create new work item. + Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem = + Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>> + ([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *) + { + // Add a reference since we need to access the completionHandle after the thread_start_function. + // This is to handle cases where detach() was called and run_thread_exit_callbacks() would end + // up closing the handle. + ::boost::detail::thread_data_base* const thread_info(reinterpret_cast<::boost::detail::thread_data_base*>(parameter)); + intrusive_ptr_add_ref(thread_info); + + __try + { + address(parameter); + } + __finally + { + SetEvent(completionHandle); + intrusive_ptr_release(thread_info); + } + return S_OK; + }); + + // Schedule work item on the threadpool. + Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> asyncAction; + hr = threadPoolFactory->RunWithPriorityAndOptionsAsync( + workItem.Get(), + ABI::Windows::System::Threading::WorkItemPriority_Normal, + ABI::Windows::System::Threading::WorkItemOptions_TimeSliced, + &asyncAction); + return hr == S_OK; + } + } +#endif + + namespace + { + void run_thread_exit_callbacks() + { + detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false); + if(current_thread_data) + { + while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks) + { + while(current_thread_data->thread_exit_callbacks) + { + detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks; + current_thread_data->thread_exit_callbacks=current_node->next; + if(current_node->func) + { + (*current_node->func)(); + boost::detail::heap_delete(current_node->func); + } + boost::detail::heap_delete(current_node); + } + while (!current_thread_data->tss_data.empty()) + { + std::map<void const*,detail::tss_data_node>::iterator current + = current_thread_data->tss_data.begin(); + if(current->second.func && (current->second.value!=0)) + { + (*current->second.caller)(current->second.func,current->second.value); + } + current_thread_data->tss_data.erase(current); + } + } + set_current_thread_data(0); + } + } + + unsigned __stdcall thread_start_function(void* param) + { + detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param)); + set_current_thread_data(thread_info); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_TRY + { +#endif + thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } + BOOST_CATCH(thread_interrupted const&) + { + } + // Unhandled exceptions still cause the application to terminate + BOOST_CATCH_END +#endif + run_thread_exit_callbacks(); + return 0; + } + } + + thread::thread() BOOST_NOEXCEPT + {} + + bool thread::start_thread_noexcept() + { +#if BOOST_PLAT_WINDOWS_RUNTIME + intrusive_ptr_add_ref(thread_info.get()); + if (!thread_info->thread_handle.start(&thread_start_function, thread_info.get(), &thread_info->id)) + { + intrusive_ptr_release(thread_info.get()); + return false; + } + return true; +#else + uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); + if(!new_thread) + { + return false; + } + intrusive_ptr_add_ref(thread_info.get()); + thread_info->thread_handle=(detail::win32::handle)(new_thread); + ResumeThread(thread_info->thread_handle); + return true; +#endif + } + + bool thread::start_thread_noexcept(const attributes& attr) + { +#if BOOST_PLAT_WINDOWS_RUNTIME + // Stack size isn't supported with Windows Runtime. + attr; + return start_thread_noexcept(); +#else + uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(), + CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_info->id); + if(!new_thread) + { + return false; + } + intrusive_ptr_add_ref(thread_info.get()); + thread_info->thread_handle=(detail::win32::handle)(new_thread); + ResumeThread(thread_info->thread_handle); + return true; +#endif + } + + thread::thread(detail::thread_data_ptr data): + thread_info(data) + {} + + namespace + { + struct externally_launched_thread: + detail::thread_data_base + { + externally_launched_thread() + { + ++count; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + interruption_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); +//#ifndef BOOST_NO_EXCEPTIONS + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); +//#endif + } + + void run() + {} + void notify_all_at_thread_exit(condition_variable*, mutex*) + {} + + private: + externally_launched_thread(externally_launched_thread&); + void operator=(externally_launched_thread&); + }; + + void make_external_thread_data() + { + externally_launched_thread* me=detail::heap_new<externally_launched_thread>(); + BOOST_TRY + { + set_current_thread_data(me); + } + BOOST_CATCH(...) + { + detail::heap_delete(me); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + detail::thread_data_base* get_or_make_current_thread_data() + { + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + if(!current_thread_data) + { + make_external_thread_data(); + current_thread_data=detail::get_current_thread_data(); + } + return current_thread_data; + } + } + + thread::id thread::get_id() const BOOST_NOEXCEPT + { +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(!local_thread_info) + { + return 0; + } + return local_thread_info->id; +#else + return thread::id((get_thread_info)()); +#endif + } + + bool thread::joinable() const BOOST_NOEXCEPT + { + detail::thread_data_ptr local_thread_info = (get_thread_info)(); + if(!local_thread_info) + { + return false; + } + return true; + } + bool thread::join_noexcept() + { + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + this_thread::interruptible_wait(this->native_handle(), detail::internal_platform_timepoint::getMax()); + release_handle(); + return true; + } + else + { + return false; + } + } + + bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res) + { + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + if(!this_thread::interruptible_wait(this->native_handle(), timeout)) + { + res=false; + return true; + } + release_handle(); + res=true; + return true; + } + else + { + return false; + } + } + + void thread::detach() + { + release_handle(); + } + + void thread::release_handle() + { + thread_info=0; + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void thread::interrupt() + { + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(local_thread_info) + { + local_thread_info->interrupt(); + } + } + + bool thread::interruption_requested() const BOOST_NOEXCEPT + { + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + return local_thread_info.get() && (winapi::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0); + } + +#endif + + unsigned thread::hardware_concurrency() BOOST_NOEXCEPT + { + detail::win32::system_info info; + detail::win32::get_system_info(&info); + return info.dwNumberOfProcessors; + } + + unsigned thread::physical_concurrency() BOOST_NOEXCEPT + { + // a bit too strict: Windows XP with SP3 would be sufficient +#if BOOST_PLAT_WINDOWS_RUNTIME \ + || ( BOOST_USE_WINAPI_VERSION <= BOOST_WINAPI_VERSION_WINXP ) \ + || ( ( defined(__MINGW32__) && !defined(__MINGW64__) ) && _WIN32_WINNT < 0x0600) + return 0; +#else + unsigned cores = 0; + DWORD size = 0; + + GetLogicalProcessorInformation(NULL, &size); + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + return 0; + const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + + std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(Elements); + if (GetLogicalProcessorInformation(&buffer.front(), &size) == FALSE) + return 0; + + + for (size_t i = 0; i < Elements; ++i) { + if (buffer[i].Relationship == RelationProcessorCore) + ++cores; + } + return cores; +#endif + } + + thread::native_handle_type thread::native_handle() + { + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(!local_thread_info) + { + return detail::win32::invalid_handle_value; + } +#if BOOST_PLAT_WINDOWS_RUNTIME + // There is no 'real' Win32 handle so we return a handle that at least can be waited on. + return local_thread_info->thread_handle.waitable_handle(); +#else + return (detail::win32::handle)local_thread_info->thread_handle; +#endif + } + + detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const + { + return thread_info; + } + + namespace this_thread + { +#ifndef UNDER_CE +#if !BOOST_PLAT_WINDOWS_RUNTIME + namespace detail_ + { + typedef struct _REASON_CONTEXT { + ULONG Version; + DWORD Flags; + union { + LPWSTR SimpleReasonString; + struct { + HMODULE LocalizedReasonModule; + ULONG LocalizedReasonId; + ULONG ReasonStringCount; + LPWSTR *ReasonStrings; + } Detailed; + } Reason; + } REASON_CONTEXT, *PREASON_CONTEXT; + typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG); + static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay) + { + return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE); + } +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail +#endif + static inline setwaitabletimerex_t SetWaitableTimerEx() + { + static setwaitabletimerex_t setwaitabletimerex_impl; + if(setwaitabletimerex_impl) + return setwaitabletimerex_impl; + void (*addr)()=(void (*)()) GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "SetWaitableTimerEx"); + if(addr) + setwaitabletimerex_impl=(setwaitabletimerex_t) addr; + else + setwaitabletimerex_impl=&SetWaitableTimerEx_emulation; + return setwaitabletimerex_impl; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } +#endif +#endif + bool interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout) + { + detail::win32::handle handles[4]={0}; + unsigned handle_count=0; + unsigned wait_handle_index=~0U; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + unsigned interruption_index=~0U; +#endif + unsigned timeout_index=~0U; + if(handle_to_wait_for!=detail::win32::invalid_handle_value) + { + wait_handle_index=handle_count; + handles[handle_count++]=handle_to_wait_for; + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled) + { + interruption_index=handle_count; + handles[handle_count++]=detail::get_current_thread_data()->interruption_handle; + } +#endif + detail::win32::handle_manager timer_handle; + +#ifndef UNDER_CE +#if !BOOST_PLAT_WINDOWS_RUNTIME + // Preferentially use coalescing timers for better power consumption and timer accuracy + if(timeout != detail::internal_platform_timepoint::getMax()) + { + boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) + { + ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 + if(time_left_msec/20>tolerable) // 5% + tolerable=static_cast<ULONG>(time_left_msec/20); + LARGE_INTEGER due_time={{0,0}}; + if(time_left_msec>0) + { + due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time + } + bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0; + if(set_time_succeeded) + { + timeout_index=handle_count; + handles[handle_count++]=timer_handle; + } + } + } +#endif +#endif + + bool const using_timer=timeout_index!=~0u; + boost::intmax_t time_left_msec(INFINITE); + if(!using_timer && timeout != detail::internal_platform_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + if(time_left_msec < 0) + { + time_left_msec = 0; + } + } + + do + { + if(handle_count) + { + unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0); + if(notified_index<handle_count) + { + if(notified_index==wait_handle_index) + { + return true; + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + else if(notified_index==interruption_index) + { + winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle); + throw thread_interrupted(); + } +#endif + else if(notified_index==timeout_index) + { + return false; + } + } + } + else + { + detail::win32::sleep(static_cast<unsigned long>(time_left_msec)); + } + + if(!using_timer && timeout != detail::internal_platform_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + } + } + while(time_left_msec == INFINITE || time_left_msec > 0); + return false; + } + + namespace no_interruption_point + { + bool non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout) + { + detail::win32::handle handles[3]={0}; + unsigned handle_count=0; + unsigned wait_handle_index=~0U; + unsigned timeout_index=~0U; + if(handle_to_wait_for!=detail::win32::invalid_handle_value) + { + wait_handle_index=handle_count; + handles[handle_count++]=handle_to_wait_for; + } + detail::win32::handle_manager timer_handle; + +#ifndef UNDER_CE +#if !BOOST_PLAT_WINDOWS_RUNTIME + // Preferentially use coalescing timers for better power consumption and timer accuracy + if(timeout != detail::internal_platform_timepoint::getMax()) + { + boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + timer_handle=CreateWaitableTimer(NULL,false,NULL); + if(timer_handle!=0) + { + ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26 + if(time_left_msec/20>tolerable) // 5% + tolerable=static_cast<ULONG>(time_left_msec/20); + LARGE_INTEGER due_time={{0,0}}; + if(time_left_msec>0) + { + due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time + } + bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0; + if(set_time_succeeded) + { + timeout_index=handle_count; + handles[handle_count++]=timer_handle; + } + } + } +#endif +#endif + + bool const using_timer=timeout_index!=~0u; + boost::intmax_t time_left_msec(INFINITE); + if(!using_timer && timeout != detail::internal_platform_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + if(time_left_msec < 0) + { + time_left_msec = 0; + } + } + + do + { + if(handle_count) + { + unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0); + if(notified_index<handle_count) + { + if(notified_index==wait_handle_index) + { + return true; + } + else if(notified_index==timeout_index) + { + return false; + } + } + } + else + { + detail::win32::sleep(static_cast<unsigned long>(time_left_msec)); + } + + if(!using_timer && timeout != detail::internal_platform_timepoint::getMax()) + { + time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs(); + } + } + while(time_left_msec == INFINITE || time_left_msec > 0); + return false; + } + } + + thread::id get_id() BOOST_NOEXCEPT + { +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#if BOOST_PLAT_WINDOWS_RUNTIME + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + if (current_thread_data) + { + return current_thread_data->id; + } +#endif + return winapi::GetCurrentThreadId(); +#else + return thread::id(get_or_make_current_thread_data()); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void interruption_point() + { + if(interruption_enabled() && interruption_requested()) + { + winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle); + throw thread_interrupted(); + } + } + + bool interruption_enabled() BOOST_NOEXCEPT + { + return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled; + } + + bool interruption_requested() BOOST_NOEXCEPT + { + return detail::get_current_thread_data() && (winapi::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0); + } +#endif + + void yield() BOOST_NOEXCEPT + { + detail::win32::sleep(0); + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + disable_interruption::disable_interruption() BOOST_NOEXCEPT: + interruption_was_enabled(interruption_enabled()) + { + if(interruption_was_enabled) + { + detail::get_current_thread_data()->interruption_enabled=false; + } + } + + disable_interruption::~disable_interruption() BOOST_NOEXCEPT + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled; + } + } + + restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT + { + if(d.interruption_was_enabled) + { + detail::get_current_thread_data()->interruption_enabled=true; + } + } + + restore_interruption::~restore_interruption() BOOST_NOEXCEPT + { + if(detail::get_current_thread_data()) + { + detail::get_current_thread_data()->interruption_enabled=false; + } + } +#endif + } + + namespace detail + { + void add_thread_exit_function(thread_exit_function_base* func) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + thread_exit_callback_node* const new_node= + heap_new<thread_exit_callback_node>( + func,current_thread_data->thread_exit_callbacks); + current_thread_data->thread_exit_callbacks=new_node; + } + + tss_data_node* find_tss_data(void const* key) + { + detail::thread_data_base* const current_thread_data(get_current_thread_data()); + if(current_thread_data) + { + std::map<void const*,tss_data_node>::iterator current_node= + current_thread_data->tss_data.find(key); + if(current_node!=current_thread_data->tss_data.end()) + { + return ¤t_node->second; + } + } + return NULL; + } + + void* get_tss_data(void const* key) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + return current_node->value; + } + return NULL; + } + + void add_new_tss_node(void const* key, + detail::tss_data_node::cleanup_caller_t caller, + detail::tss_data_node::cleanup_func_t func, + void* tss_data) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(caller,func,tss_data))); + } + + void erase_tss_node(void const* key) + { + detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); + current_thread_data->tss_data.erase(key); + } + + void set_tss_data(void const* key, + detail::tss_data_node::cleanup_caller_t caller, + detail::tss_data_node::cleanup_func_t func, + void* tss_data,bool cleanup_existing) + { + if(tss_data_node* const current_node=find_tss_data(key)) + { + if(cleanup_existing && current_node->func && (current_node->value!=0)) + { + (*current_node->caller)(current_node->func,current_node->value); + } + if(func || (tss_data!=0)) + { + current_node->caller=caller; + current_node->func=func; + current_node->value=tss_data; + } + else + { + erase_tss_node(key); + } + } + else if(func || (tss_data!=0)) + { + add_new_tss_node(key,caller,func,tss_data); + } + } + } + + BOOST_THREAD_DECL void __cdecl on_process_enter() + {} + + BOOST_THREAD_DECL void __cdecl on_thread_enter() + {} + + BOOST_THREAD_DECL void __cdecl on_process_exit() + { + boost::cleanup_tls_key(); + } + + BOOST_THREAD_DECL void __cdecl on_thread_exit() + { + boost::run_thread_exit_callbacks(); + } + + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); + } + } +} + diff --git a/src/boost/libs/thread/src/win32/thread_primitives.cpp b/src/boost/libs/thread/src/win32/thread_primitives.cpp new file mode 100644 index 000000000..5f6e6f03a --- /dev/null +++ b/src/boost/libs/thread/src/win32/thread_primitives.cpp @@ -0,0 +1,156 @@ +// thread_primitives.cpp +// +// (C) Copyright 2018 Andrey Semashev +// +// 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 <boost/winapi/config.hpp> +#include <boost/winapi/dll.hpp> +#include <boost/winapi/time.hpp> +#include <boost/winapi/event.hpp> +#include <boost/winapi/handles.hpp> +#include <boost/winapi/thread_pool.hpp> +#include <cstdlib> +#include <boost/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/memory_order.hpp> +#include <boost/atomic/atomic.hpp> +#include <boost/thread/win32/interlocked_read.hpp> +#include <boost/thread/win32/thread_primitives.hpp> + +namespace boost { +namespace detail { +namespace win32 { + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +// Directly use API from Vista and later +BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64 = &::boost::winapi::GetTickCount64; + +#else // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +namespace { + +enum init_state +{ + uninitialized = 0, + in_progress, + initialized +}; + +struct get_tick_count64_state +{ + boost::atomic< uint64_t > ticks; + boost::atomic< init_state > init; + boost::winapi::HANDLE_ wait_event; + boost::winapi::HANDLE_ wait_handle; +}; + +// Zero-initialized initially +BOOST_ALIGNMENT(64) static get_tick_count64_state g_state; + +//! Artifical implementation of GetTickCount64 +ticks_type WINAPI get_tick_count64() +{ + uint64_t old_state = g_state.ticks.load(boost::memory_order_acquire); + + uint32_t new_ticks = boost::winapi::GetTickCount(); + + uint32_t old_ticks = static_cast< uint32_t >(old_state & UINT64_C(0x00000000ffffffff)); + uint64_t new_state = ((old_state & UINT64_C(0xffffffff00000000)) + (static_cast< uint64_t >(new_ticks < old_ticks) << 32)) | static_cast< uint64_t >(new_ticks); + + g_state.ticks.store(new_state, boost::memory_order_release); + + return new_state; +} + +//! The function is called periodically in the system thread pool to make sure g_state.ticks is timely updated +void NTAPI refresh_get_tick_count64(boost::winapi::PVOID_, boost::winapi::BOOLEAN_) +{ + get_tick_count64(); +} + +//! Cleanup function to stop get_tick_count64 refreshes +void cleanup_get_tick_count64() +{ + if (g_state.wait_handle) + { + boost::winapi::UnregisterWait(g_state.wait_handle); + g_state.wait_handle = NULL; + } + + if (g_state.wait_event) + { + boost::winapi::CloseHandle(g_state.wait_event); + g_state.wait_event = NULL; + } +} + +ticks_type WINAPI get_tick_count_init() +{ + boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll"); + if (hKernel32) + { + // GetProcAddress returns a pointer to some function. It can return + // pointers to different functions, so it has to return something that is + // suitable to store any pointer to function. Microsoft chose FARPROC, + // which is int (WINAPI *)() on 32-bit Windows. The user is supposed to + // know the signature of the function he requests and perform a cast + // (which is a nop on this platform). The result is a pointer to function + // with the required signature, which is bitwise equal to what + // GetProcAddress returned. + // However, gcc >= 8 warns about that. +#if defined(BOOST_GCC) && BOOST_GCC >= 80000 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + boost::detail::win32::detail::gettickcount64_t p = + (boost::detail::win32::detail::gettickcount64_t)boost::winapi::get_proc_address(hKernel32, "GetTickCount64"); +#if defined(BOOST_GCC) && BOOST_GCC >= 80000 +#pragma GCC diagnostic pop +#endif + if (p) + { + // Use native API + boost::detail::interlocked_write_release((void**)&gettickcount64, (void*)p); + return p(); + } + } + + // No native API available. Use emulation with periodic refreshes to make sure the GetTickCount wrap arounds are properly counted. + init_state old_init = uninitialized; + if (g_state.init.compare_exchange_strong(old_init, in_progress, boost::memory_order_acq_rel, boost::memory_order_relaxed)) + { + if (!g_state.wait_event) + g_state.wait_event = boost::winapi::create_anonymous_event(NULL, false, false); + if (g_state.wait_event) + { + boost::winapi::BOOL_ res = boost::winapi::RegisterWaitForSingleObject(&g_state.wait_handle, g_state.wait_event, &refresh_get_tick_count64, NULL, 0x7fffffff, boost::winapi::WT_EXECUTEINWAITTHREAD_); + if (res) + { + std::atexit(&cleanup_get_tick_count64); + + boost::detail::interlocked_write_release((void**)&gettickcount64, (void*)&get_tick_count64); + g_state.init.store(initialized, boost::memory_order_release); + goto finish; + } + } + + g_state.init.store(uninitialized, boost::memory_order_release); + } + +finish: + return get_tick_count64(); +} + +} // namespace + +BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64 = &get_tick_count_init; + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +} // namespace win32 +} // namespace detail +} // namespace boost diff --git a/src/boost/libs/thread/src/win32/tss_dll.cpp b/src/boost/libs/thread/src/win32/tss_dll.cpp new file mode 100644 index 000000000..caddabf0b --- /dev/null +++ b/src/boost/libs/thread/src/win32/tss_dll.cpp @@ -0,0 +1,85 @@ +// (C) Copyright Michael Glassford 2004. +// Use, modification and distribution are subject to 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 <boost/winapi/config.hpp> +#include <boost/thread/detail/config.hpp> + + +#if defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL) + + #include <boost/thread/detail/tss_hooks.hpp> + + #include <windows.h> + + #if defined(__BORLANDC__) + extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #elif defined(_WIN32_WCE) + extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #else + extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/) + #endif + { + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + { + boost::on_process_enter(); + boost::on_thread_enter(); + break; + } + + case DLL_THREAD_ATTACH: + { + boost::on_thread_enter(); + break; + } + + case DLL_THREAD_DETACH: + { + boost::on_thread_exit(); + break; + } + + case DLL_PROCESS_DETACH: + { + boost::on_thread_exit(); + boost::on_process_exit(); + break; + } + } + + return TRUE; + } + +namespace boost +{ + void tss_cleanup_implemented() + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } +} + +#else //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL) + +#ifdef _MSC_VER +// Prevent LNK4221 warning with link=static +namespace boost { namespace link_static_warning_inhibit { + extern __declspec(dllexport) void foo() { } +} } +#endif + +#endif //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL) diff --git a/src/boost/libs/thread/src/win32/tss_pe.cpp b/src/boost/libs/thread/src/win32/tss_pe.cpp new file mode 100644 index 000000000..be4d8a7ac --- /dev/null +++ b/src/boost/libs/thread/src/win32/tss_pe.cpp @@ -0,0 +1,337 @@ +// $Id$ +// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. +// (C) Copyright 2007 Roland Schwarz +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins +// Use, modification and distribution are subject to 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 <boost/winapi/config.hpp> +#include <boost/thread/detail/config.hpp> + +#if defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB) + +#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) + +#include <boost/thread/detail/tss_hooks.hpp> + +#include <windows.h> + +#include <cstdlib> + +namespace boost +{ + void tss_cleanup_implemented() {} +} + +namespace { + void NTAPI on_tls_callback(void* , DWORD dwReason, PVOID ) + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + { + boost::on_thread_exit(); + break; + } + } + } +} + +#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__MINGW32_MAJOR_VERSION >3) || \ + ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18)) +extern "C" +{ + PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; +} +#else +extern "C" { + + void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter; + void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit; + void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit; + + ULONG __tls_index__ = 0; + char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; + char __tls_start__ __attribute__((section(".tls"))) = 0; + + + PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; + PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; +} +extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = +{ + (DWORD) &__tls_start__, + (DWORD) &__tls_end__, + (DWORD) &__tls_index__, + (DWORD) (&__crt_xl_start__+1), + (DWORD) 0, + (DWORD) 0 +}; +#endif + + +#elif defined(_MSC_VER) && !defined(UNDER_CE) + + #include <boost/thread/detail/tss_hooks.hpp> + + #include <stdlib.h> + + #include <windows.h> + + +// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp +// into your dll; it ensures that MFC-Dll-initialization will be done properly +// The following code is adapted from the MFC-Dll-init code +/* + * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to + * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the + * alternatename directive. + */ + +// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008) +#if (_MSC_VER >= 1500) + +extern "C" { +extern BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID); +extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = NULL; +#if defined (_M_IX86) +#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig") +#elif defined (_M_X64) || defined (_M_ARM) || defined (_M_ARM64) +#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig") +#else /* unknown Windows target (not x86, x64, ARM, ARM64) */ +#error Unsupported platform +#endif /* defined (_M_X64) || defined (_M_ARM) || defined (_M_ARM64) */ +} + +#endif + + + + + //Definitions required by implementation + #if (_MSC_VER < 1300) || ((_MSC_VER > 1900) && (_MSC_VER < 1910)) // 1300 == VC++ 7.0, 1900 == VC++ 14.0, 1910 == VC++ 2017 + typedef void ( __cdecl *_PVFV_ )(); + typedef void ( __cdecl *_PIFV_ )(); + #define INIRETSUCCESS_V + #define INIRETSUCCESS_I + #define PVAPI_V void __cdecl + #define PVAPI_I void __cdecl + #elif (_MSC_VER >= 1910) + typedef void ( __cdecl *_PVFV_ )(); + typedef int ( __cdecl *_PIFV_ )(); + #define INIRETSUCCESS_V + #define INIRETSUCCESS_I 0 + #define PVAPI_V void __cdecl + #define PVAPI_I int __cdecl + #else + typedef int ( __cdecl *_PVFV_ )(); + typedef int ( __cdecl *_PIFV_ )(); + #define INIRETSUCCESS_V 0 + #define INIRETSUCCESS_I 0 + #define PVAPI_V int __cdecl + #define PVAPI_I int __cdecl + #endif + + typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); + + //Symbols for connection to the runtime environment + + extern "C" + { + extern DWORD _tls_used; //the tls directory (located in .rdata segment) + extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */ + } + + namespace + { + //Forward declarations + + static PVAPI_I on_tls_prepare(); + static PVAPI_V on_process_init(); + static PVAPI_V on_process_term(); + static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); + + //The .CRT$Xxx information is taken from Codeguru: + //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ + +#if (_MSC_VER >= 1400) +#pragma section(".CRT$XIU",long,read) +#pragma section(".CRT$XCU",long,read) +#pragma section(".CRT$XTU",long,read) +#pragma section(".CRT$XLC",long,read) + __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; + __declspec(allocate(".CRT$XIU"))_PIFV_ p_tls_prepare = on_tls_prepare; + __declspec(allocate(".CRT$XCU"))_PVFV_ p_process_init = on_process_init; + __declspec(allocate(".CRT$XTU"))_PVFV_ p_process_term = on_process_term; +#else + #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 + # pragma data_seg(push, old_seg) + #endif + //Callback to run tls glue code first. + //I don't think it is necessary to run it + //at .CRT$XIB level, since we are only + //interested in thread detachement. But + //this could be changed easily if required. + + #pragma data_seg(".CRT$XIU") + static _PIFV_ p_tls_prepare = on_tls_prepare; + #pragma data_seg() + + //Callback after all global ctors. + + #pragma data_seg(".CRT$XCU") + static _PVFV_ p_process_init = on_process_init; + #pragma data_seg() + + //Callback for tls notifications. + + #pragma data_seg(".CRT$XLB") + _TLSCB p_thread_callback = on_tls_callback; + #pragma data_seg() + //Callback for termination. + + #pragma data_seg(".CRT$XTU") + static _PVFV_ p_process_term = on_process_term; + #pragma data_seg() + #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 + # pragma data_seg(pop, old_seg) + #endif +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4189) +#endif + + PVAPI_I on_tls_prepare() + { + //The following line has an important side effect: + //if the TLS directory is not already there, it will + //be created by the linker. In other words, it forces a tls + //directory to be generated by the linker even when static tls + //(i.e. __declspec(thread)) is not used. + //The volatile should prevent the optimizer + //from removing the reference. + + DWORD volatile dw = _tls_used; + + #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 + _TLSCB* pfbegin = __xl_a; + _TLSCB* pfend = __xl_z; + _TLSCB* pfdst = pfbegin; + //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; + + //The following loop will merge the address pointers + //into a contiguous area, since the tlssup code seems + //to require this (at least on MSVC 6) + + while (pfbegin < pfend) + { + if (*pfbegin != 0) + { + *pfdst = *pfbegin; + ++pfdst; + } + ++pfbegin; + } + + *pfdst = 0; + #endif + + return INIRETSUCCESS_I; + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + PVAPI_V on_process_init() + { + //Schedule on_thread_exit() to be called for the main + //thread before destructors of global objects have been + //called. + + //It will not be run when 'quick' exiting the + //library; however, this is the standard behaviour + //for destructors of global objects, so that + //shouldn't be a problem. + + atexit(boost::on_thread_exit); + + //Call Boost process entry callback here + + boost::on_process_enter(); + + return INIRETSUCCESS_V; + } + + PVAPI_V on_process_term() + { + boost::on_process_exit(); + return INIRETSUCCESS_V; + } + + void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + boost::on_thread_exit(); + break; + } + } + +#if (_MSC_VER >= 1500) + BOOL WINAPI dll_callback(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +#else + BOOL WINAPI dll_callback(HINSTANCE, DWORD dwReason, LPVOID) +#endif + { + switch (dwReason) + { + case DLL_THREAD_DETACH: + boost::on_thread_exit(); + break; + case DLL_PROCESS_DETACH: + boost::on_process_exit(); + break; + } + +#if (_MSC_VER >= 1500) + if( _pRawDllMainOrig ) + { + return _pRawDllMainOrig(hInstance, dwReason, lpReserved); + } +#endif + return true; + } + } //namespace + +extern "C" +{ + extern BOOL (WINAPI * const _pRawDllMain)(HINSTANCE, DWORD, LPVOID)=&dll_callback; +} +namespace boost +{ + void tss_cleanup_implemented() + { + /* + This function's sole purpose is to cause a link error in cases where + automatic tss cleanup is not implemented by Boost.Threads as a + reminder that user code is responsible for calling the necessary + functions at the appropriate times (and for implementing an a + tss_cleanup_implemented() function to eliminate the linker's + missing symbol error). + + If Boost.Threads later implements automatic tss cleanup in cases + where it currently doesn't (which is the plan), the duplicate + symbol error will warn the user that their custom solution is no + longer needed and can be removed. + */ + } +} + +#endif //defined(_MSC_VER) && !defined(UNDER_CE) + +#endif //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB) diff --git a/src/boost/libs/thread/test/Carbon.r b/src/boost/libs/thread/test/Carbon.r new file mode 100644 index 000000000..e0ac5b449 --- /dev/null +++ b/src/boost/libs/thread/test/Carbon.r @@ -0,0 +1,18 @@ +/* + * Permit this Carbon application to launch on OS X + * + * © 1997-2000 Metrowerks Corp. + * + * Questions and comments to: + * <mailto:support@metrowerks.com> + * <http://www.metrowerks.com/> + */ + + +/*----------------------------carb ¥ Carbon on OS X launch information --------------------------*/ +type 'carb' { +}; + + +resource 'carb'(0) { +}; diff --git a/src/boost/libs/thread/test/Jamfile.v2 b/src/boost/libs/thread/test/Jamfile.v2 new file mode 100644 index 000000000..5788c83d8 --- /dev/null +++ b/src/boost/libs/thread/test/Jamfile.v2 @@ -0,0 +1,1098 @@ +# (C) Copyright William E. Kempf 2001. +# (C) Copyright 2007 Anthony Williams. +# (C) Copyright 2011-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) +# +# Boost.Threads test Jamfile +# +# Additional configuration variables used: +# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32 +# library should be used instead of "native" threads. This feature is +# mostly used for testing and it's generally recommended you use the +# native threading libraries instead. PTW32 should be set to be a list +# of two strings, the first specifying the installation path of the +# pthreads-win32 library and the second specifying which library +# variant to link against (see the pthreads-win32 documentation). +# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib" + +# bring in rules for testing +import testing ; +import regex ; +import path ; +import os ; + +project + : requirements + <threading>multi + + <define>BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + + <warnings>all + <toolset>gcc:<cxxflags>-Wextra + <toolset>gcc:<cxxflags>-pedantic + <toolset>gcc:<cxxflags>-Wno-long-long + #<toolset>gcc:<cxxflags>-ansi + #<toolset>gcc:<cxxflags>-fpermissive + <toolset>gcc-4:<cxxflags>-Wno-variadic-macros + <toolset>gcc-5:<cxxflags>-Wno-variadic-macros + #<toolset>gcc:<cxxflags>-Wunused-local-typedefs + <toolset>gcc:<cxxflags>-Wunused-function + <toolset>gcc:<cxxflags>-Wno-unused-parameter + + <toolset>darwin:<cxxflags>-Wextra + <toolset>darwin:<cxxflags>-pedantic + <toolset>darwin:<cxxflags>-Wno-long-long + #<toolset>darwin:<cxxflags>-ansi # doesn't work for 4.1.2 + <toolset>darwin:<cxxflags>-fpermissive + <toolset>darwin:<cxxflags>-Wno-variadic-macros + #<toolset>darwin:<cxxflags>-Wunused-local-typedefs + <toolset>darwin:<cxxflags>-Wunused-function + <toolset>darwin:<cxxflags>-Wno-unused-parameter + + #<toolset>pathscale:<cxxflags>-Wextra + <toolset>pathscale:<cxxflags>-Wno-long-long + <toolset>pathscale:<cxxflags>-pedantic + + <toolset>clang:<warnings>on + <toolset>clang:<cxxflags>-Wextra + #<toolset>clang:<cxxflags>-pedantic + <toolset>clang:<cxxflags>-Wno-long-long + #<toolset>clang:<cxxflags>-ansi + #<toolset>clang:<cxxflags>-fpermissive # doesn't work + <toolset>clang:<cxxflags>-Wunused-function + <toolset>clang:<cxxflags>-Wno-unused-parameter + + #<toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.6.3:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.7.0:<cxxflags>-fdiagnostics-show-option + #<toolset>gcc-mingw-4.8.0:<cxxflags>-fdiagnostics-show-option + + <toolset>darwin-4.6.2:<cxxflags>-ansi + #<toolset>darwin-4.6.2:<cxxflags>-Wno-delete-non-virtual-dtor # doesn't work + <toolset>darwin-4.7.0:<cxxflags>-ansi + <toolset>darwin-4.7.0:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>darwin-4.6.2:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.1:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.2:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.8.0:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.6.2x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.1x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.7.2x:<cxxflags>-Wno-unused-local-typedefs + #<toolset>darwin-4.8.0x:<cxxflags>-Wno-unused-local-typedefs + + #<toolset>clang-2.8:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.8:<cxxflags>-Wno-unused-function + #<toolset>clang-2.9:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-2.9:<cxxflags>-Wno-unused-function + <toolset>clang-3.0:<cxxflags>-Wno-delete-non-virtual-dtor + #<toolset>clang-3.0:<cxxflags>-Wno-unused-function + #<toolset>clang-3.0:<cxxflags>-Wno-unused-variable + #<toolset>clang-3.1:<cxxflags>-Wno-bind-to-temporary-copy + #<toolset>clang-3.2:<cxxflags>-Wno-bind-to-temporary-copy + +# Note: Some of the remarks from the Intel compiler are disabled +# remark #193: zero used for undefined preprocessing identifier "XXX" +# remark #304: access control not specified ("public" by default) +# remark #593: variable "XXX" was set but never used +# remark #1418: external function definition with no prior declaration +# remark #2415: variable "XXX" of static storage duration was declared but never referenced + + <toolset>intel:<cxxflags>-wd193,304,383,444 + <toolset>intel:<cxxflags>-wd593,981 + <toolset>intel:<cxxflags>-wd1418 + <toolset>intel:<cxxflags>-wd2415 + + <toolset>msvc:<cxxflags>/wd4100 + <toolset>msvc:<cxxflags>/wd4512 + <toolset>msvc:<cxxflags>/wd6246 + ; + +rule thread-run ( sources ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : : $(sources[1]:B)_lib ] + ; +} + + +rule thread-test ( sources ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : + <library>/boost/test//boost_unit_test_framework + ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + <library>/boost/test//boost_unit_test_framework/<link>static + : $(sources[1]:B)_lib + ] + ; +} + +rule thread-run2 ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + : $(name)_lib ] + ; +} + +rule thread-run2-noit ( sources : name : reqs * ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : $(reqs) + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : $(reqs) + : $(name)_lib ] + #[ run $(sources) ../build//boost_thread : : : + # <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + # : $(name)_noit ] + ; +} + +rule thread-run2-noit-pthread ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../build//boost_thread : : : <threadapi>win32:<build>no + : $(name) ] + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : <threadapi>win32:<build>no + : $(name)_lib ] + #[ run $(sources) ../build//boost_thread : : : + # <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + # : $(name)_noit ] + ; +} + +rule thread-run2-h ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) : : : + <define>BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS + <define>BOOST_THREAD_VERSION=3 + : $(name)_h ] + ; +} + + +rule thread-run-lib2 ( sources : name ) +{ + sources = $(sources) winrt_init.cpp ; + return + [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static + : : : + : $(name)_lib ] + ; +} + + +rule thread-compile-fail ( sources : reqs * : name ) +{ + return + [ compile-fail $(sources) + : $(reqs) + : $(name) ] + ; +} + +rule clang-thread-safety ( properties * ) +{ + if <toolset>clang in $(properties) + { + return <cxxflags>-Werror=thread-safety <define>BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS ; + } + else + { + return <build>no ; + } +} + +rule thread-safety-compile ( sources : reqs * : name ) +{ + return + [ compile $(sources) + : $(reqs) <conditional>@clang-thread-safety + : $(name) ] + ; +} + +rule thread-safety-compile-fail ( sources : reqs * : name ) +{ + return + [ compile-fail $(sources) + : $(reqs) <conditional>@clang-thread-safety + : $(name) ] + ; +} + +rule thread-compile ( sources : reqs * : name ) +{ + return + [ compile $(sources) + : $(reqs) + : $(name) ] + ; +} + +rule windows-cygwin-specific ( properties * ) +{ + if <target-os>windows in $(properties) || <target-os>cygwin in $(properties) + { + return <build>yes ; + } + else + { + return <build>no ; + } +} + +rule generate_self_contained_header_tests +{ + local all_rules ; + local file ; + + if ! [ os.environ BOOST_THREAD_TEST_WITHOUT_SELF_CONTAINED_HEADER_TESTS ] + { + local headers_path = [ path.make $(BOOST_ROOT)/libs/thread/include/boost/thread ] ; + for file in [ path.glob-tree $(headers_path) : *.hpp : detail pthread win32 ] + { + local rel_file = [ path.relative-to $(headers_path) $(file) ] ; + # Note: The test name starts with '~' in order to group these tests in the test report table, preferably at the end. + # All '/' are replaced with '-' because apparently test scripts have a problem with test names containing slashes. + local test_name = [ regex.replace ~hdr/$(rel_file) "/" "-" ] ; + #ECHO $(rel_file) ; + all_rules += [ compile self_contained_header.cpp : <define>"BOOST_THREAD_TEST_HEADER=$(rel_file)" <dependency>$(file) : $(test_name) ] ; + all_rules += [ compile self_contained_header.cpp : <define>"BOOST_THREAD_TEST_HEADER=$(rel_file)" <define>"BOOST_THREAD_TEST_POST_WINDOWS_H" <dependency>$(file) <conditional>@windows-cygwin-specific : $(test_name)-post_winh ] ; + } + } + + #ECHO All rules: $(all_rules) ; + return $(all_rules) ; +} + +{ + test-suite t_threads + : + [ thread-test test_thread.cpp ] + [ thread-test test_thread_id.cpp ] + [ thread-test test_hardware_concurrency.cpp ] + [ thread-test test_physical_concurrency.cpp ] + [ thread-test test_thread_move.cpp ] + [ thread-test test_thread_return_local.cpp ] + [ thread-test test_thread_move_return.cpp ] + [ thread-test test_thread_launching.cpp ] + [ thread-test test_thread_mf.cpp ] + [ thread-test test_thread_exit.cpp ] + [ thread-test test_move_function.cpp ] + [ compile-fail no_implicit_move_from_lvalue_thread.cpp ] + [ compile-fail no_implicit_assign_from_lvalue_thread.cpp ] + [ thread-test test_tss.cpp ] + [ thread-test test_xtime.cpp ] + ; + + test-suite t_sync + : + [ thread-test test_mutex.cpp ] + [ thread-test test_condition_notify_one.cpp ] + [ thread-test test_condition_timed_wait_times_out.cpp ] + [ thread-test test_condition_notify_all.cpp ] + [ thread-test test_condition.cpp ] + [ thread-test test_once.cpp ] + [ thread-run test_barrier.cpp ] + [ thread-run test_barrier_void_fct.cpp ] + [ thread-run test_barrier_size_fct.cpp ] + [ thread-test test_lock_concept.cpp ] + [ thread-test test_generic_locks.cpp ] + [ thread-run test_latch.cpp ] + [ thread-run test_completion_latch.cpp ] + ; + + test-suite t_shared + : + [ thread-test test_shared_mutex.cpp ] + [ thread-test test_shared_mutex_part_2.cpp ] + [ thread-test test_shared_mutex_timed_locks.cpp ] + [ thread-test test_shared_mutex_timed_locks_chrono.cpp ] + #uncomment the following once these works on windows + #[ thread-test test_vhh_shared_mutex.cpp ] + #[ thread-test test_vhh_shared_mutex_part_2.cpp ] + #[ thread-test test_vhh_shared_mutex_timed_locks.cpp ] + ; + + explicit t_futures_too_long ; + test-suite t_futures_too_long + : + [ thread-test test_futures.cpp ] + ; + + + #explicit tickets ; + test-suite tickets + : + [ thread-test test_2309.cpp ] + [ thread-run test_2501.cpp ] + [ thread-test test_2741.cpp ] + [ thread-run test_3628.cpp ] + [ thread-run test_4521.cpp ] + [ thread-run test_4648.cpp ] + [ thread-run test_4882.cpp ] + [ thread-run test_5542_1.cpp ] + [ thread-run test_5542_2.cpp ] + [ thread-run test_5542_3.cpp ] + [ thread-run test_5891.cpp ] + #[ thread-run test_6130.cpp ] + #[ thread-run test_6170.cpp ] + [ thread-run test_6174.cpp ] + #[ thread-run test_7160.cpp ] + [ thread-run test_7328.cpp ] + [ thread-run test_7571.cpp ] + [ thread-run test_9319.cpp ] + #[ thread-run test_9711.cpp ] This is an invalid use of ::then deferred. + [ thread-run test_9856.cpp ] + [ thread-compile test_10963.cpp : : test_10963_c ] + [ thread-run test_10964.cpp ] + [ thread-test test_11053.cpp ] + [ thread-run test_11266.cpp ] + ; + + + explicit oth_tickets ; + test-suite oth_tickets + : + [ thread-run test_5351.cpp ] + [ thread-run test_5502.cpp ] + ; + + + + #explicit ts_conditions ; + test-suite ts_conditions + : + [ thread-compile-fail ./sync/conditions/condition_variable/assign_fail.cpp : : condition_variable__assign_f ] + [ thread-compile-fail ./sync/conditions/condition_variable/copy_fail.cpp : : condition_variable__copy_f ] + [ thread-run2-noit ./sync/conditions/condition_variable/default_pass.cpp : condition_variable__default_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/dtor_pass.cpp : condition_variable__dtor_p ] + [ thread-run2-noit-pthread ./sync/conditions/condition_variable/native_handle_pass.cpp : condition_variable__native_handle_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_pass.cpp : condition_variable__wait_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_for_pass.cpp : condition_variable__wait_for_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_for_pred_pass.cpp : condition_variable__wait_for_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pass.cpp : condition_variable__wait_until_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/wait_until_pred_pass.cpp : condition_variable__wait_until_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable/lost_notif_pass.cpp : condition_variable__lost_notif_p ] + + [ thread-compile-fail ./sync/conditions/condition_variable_any/assign_fail.cpp : : condition_variable_any__assign_f ] + [ thread-compile-fail ./sync/conditions/condition_variable_any/copy_fail.cpp : : condition_variable_any__copy_f ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/default_pass.cpp : condition_variable_any__default_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/dtor_pass.cpp : condition_variable_any__dtor_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_for_pass.cpp : condition_variable_any__wait_for_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_for_pred_pass.cpp : condition_variable_any__wait_for_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pass.cpp : condition_variable_any__wait_until_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/wait_until_pred_pass.cpp : condition_variable_any__wait_until_pred_p ] + [ thread-run2-noit ./sync/conditions/condition_variable_any/lost_notif_pass.cpp : condition_variable_any__lost_notif_p ] + [ thread-run2-noit ./sync/conditions/cv_status/cv_status_pass.cpp : cv_status__cv_status_p ] + [ thread-run2-noit ./sync/conditions/notify_all_at_thread_exit_pass.cpp : notify_all_at_thread_exit_p ] + ; + + #explicit ts_async ; + test-suite ts_async + : + [ thread-run2-noit ./sync/futures/async/async_pass.cpp : async__async_p ] + [ thread-run2-noit ./sync/futures/async/async_executor_pass.cpp : async__async_executor_p ] + ; + + #explicit ts_promise ; + test-suite ts_promise + : + [ thread-compile-fail ./sync/futures/promise/copy_assign_fail.cpp : : promise__copy_assign_f ] + [ thread-compile-fail ./sync/futures/promise/copy_ctor_fail.cpp : : promise__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/promise/alloc_ctor_pass.cpp : promise__alloc_ctor_p ] + [ thread-run2-noit ./sync/futures/promise/default_pass.cpp : promise__default_p ] + [ thread-run2-noit ./sync/futures/promise/dtor_pass.cpp : promise__dtor_p ] + [ thread-run2-noit ./sync/futures/promise/get_future_pass.cpp : promise__get_future_p ] + [ thread-run2-noit ./sync/futures/promise/move_ctor_pass.cpp : promise__move_ctor_p ] + [ thread-run2-noit ./sync/futures/promise/move_assign_pass.cpp : promise__move_asign_p ] + [ thread-run2-noit ./sync/futures/promise/set_exception_pass.cpp : promise__set_exception_p ] + [ thread-run2-noit ./sync/futures/promise/set_lvalue_pass.cpp : promise__set_lvalue_p ] + [ thread-run2-noit ./sync/futures/promise/set_rvalue_pass.cpp : promise__set_rvalue_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_const_pass.cpp : promise__set_value_const_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ] + [ thread-run2-noit ./sync/futures/promise/emplace_pass.cpp : promise__emplace_p ] + [ thread-run2-noit ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ] + [ thread-run2-noit ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp : promise__set_rvalue_at_thread_exit_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_const_pass.cpp : promise__set_value_at_thread_exit_const_p ] + [ thread-run2-noit ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ] + ; + + #explicit ts_make_ready_future ; + test-suite ts_make_ready_future + : + [ thread-run2-noit ./sync/futures/make_ready_future_pass.cpp : make_ready_future_p ] + ; + + #explicit ts_future ; + test-suite ts_future + : + [ thread-compile-fail ./sync/futures/future/copy_assign_fail.cpp : : future__copy_assign_f ] + [ thread-compile-fail ./sync/futures/future/copy_ctor_fail.cpp : : future__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/future/default_pass.cpp : future__default_p ] + [ thread-run2-noit ./sync/futures/future/dtor_pass.cpp : future__dtor_p ] + [ thread-run2-noit ./sync/futures/future/get_pass.cpp : future__get_p ] + [ thread-run2-noit ./sync/futures/future/get_or_pass.cpp : future__get_or_p ] + [ thread-run2-noit ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ] + [ thread-run2-noit ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ] + [ thread-run2-noit ./sync/futures/future/share_pass.cpp : future__share_p ] + [ thread-run2-noit ./sync/futures/future/wait_pass.cpp : future__wait_p ] + [ thread-run2-noit ./sync/futures/future/wait_for_pass.cpp : future__wait_for_p ] + [ thread-run2-noit ./sync/futures/future/wait_until_pass.cpp : future__wait_until_p ] + [ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ] + [ thread-run2-noit ./sync/futures/future/then_executor_pass.cpp : future__then_executor_p ] + [ thread-run2-noit ./sync/futures/future/async_deferred_then_pass.cpp : future__async_def_then_p ] + [ thread-run2-noit ./sync/futures/future/then_deferred_pass.cpp : future__then_def_p ] + ; + + #explicit ts_shared_future ; + test-suite ts_shared_future + : + [ thread-run2-noit ./sync/futures/shared_future/copy_assign_pass.cpp : shared_future__copy_assign_p ] + [ thread-run2-noit ./sync/futures/shared_future/copy_ctor_pass.cpp : shared_future__copy_ctor_p ] + [ thread-run2-noit ./sync/futures/shared_future/default_pass.cpp : shared_future__default_p ] + [ thread-run2-noit ./sync/futures/shared_future/dtor_pass.cpp : shared_future__dtor_p ] + [ thread-run2-noit ./sync/futures/shared_future/get_pass.cpp : shared_future__get_p ] + [ thread-run2-noit ./sync/futures/shared_future/move_ctor_pass.cpp : shared_future__move_ctor_p ] + [ thread-run2-noit ./sync/futures/shared_future/move_assign_pass.cpp : shared_future__move_asign_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_pass.cpp : shared_future__wait_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_for_pass.cpp : shared_future__wait_for_p ] + [ thread-run2-noit ./sync/futures/shared_future/wait_until_pass.cpp : shared_future__wait_until_p ] + [ thread-run2-noit ./sync/futures/shared_future/then_pass.cpp : shared_future__then_p ] + [ thread-run2-noit ./sync/futures/shared_future/then_executor_pass.cpp : shared_future__then_executor_p ] + ; + + #explicit ts_packaged_task ; + test-suite ts_packaged_task + : + [ thread-run2-noit ./sync/futures/packaged_task/alloc_ctor_pass.cpp : packaged_task__alloc_ctor_p ] + [ thread-compile-fail ./sync/futures/packaged_task/copy_assign_fail.cpp : : packaged_task__copy_assign_f ] + [ thread-compile-fail ./sync/futures/packaged_task/copy_ctor_fail.cpp : : packaged_task__copy_ctor_f ] + [ thread-run2-noit ./sync/futures/packaged_task/default_ctor_pass.cpp : packaged_task__default_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/func_ctor_pass.cpp : packaged_task__func_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/dtor_pass.cpp : packaged_task__dtor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/get_future_pass.cpp : packaged_task__get_future_p ] + [ thread-run2-noit ./sync/futures/packaged_task/move_ctor_pass.cpp : packaged_task__move_ctor_p ] + [ thread-run2-noit ./sync/futures/packaged_task/move_assign_pass.cpp : packaged_task__move_asign_p ] + [ thread-run2-noit ./sync/futures/packaged_task/operator_pass.cpp : packaged_task__operator_p ] + [ thread-run2-noit ./sync/futures/packaged_task/reset_pass.cpp : packaged_task__reset_p ] + [ thread-run2-noit ./sync/futures/packaged_task/use_allocator_pass.cpp : packaged_task__use_allocator_p ] + [ thread-run2-noit ./sync/futures/packaged_task/types_pass.cpp : packaged_task__types_p ] + [ thread-run2-noit ./sync/futures/packaged_task/member_swap_pass.cpp : packaged_task__member_swap_p ] + [ thread-run2-noit ./sync/futures/packaged_task/non_member_swap_pass.cpp : packaged_task__non_member_swap_p ] + [ thread-run2-noit ./sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp : packaged_task__make_ready_at_thread_exit_p ] + ; + + + #explicit ts_when_all ; + test-suite ts_when_all + : + [ thread-run2-noit ./sync/futures/when_all/none_pass.cpp : when_all__none_p ] + [ thread-run2-noit ./sync/futures/when_all/one_pass.cpp : when_all__one_p ] + [ thread-run2-noit ./sync/futures/when_all/iterators_pass.cpp : when_all__iterators_p ] + [ thread-run2-noit ./sync/futures/when_all/variadic_pass.cpp : when_all__variadic_p ] + ; + + #explicit ts_when_any ; + test-suite ts_when_any + : + [ thread-run2-noit ./sync/futures/when_any/none_pass.cpp : when_any__none_p ] + [ thread-run2-noit ./sync/futures/when_any/one_pass.cpp : when_any__one_p ] + [ thread-run2-noit ./sync/futures/when_any/iterators_pass.cpp : when_any__iterators_p ] + [ thread-run2-noit ./sync/futures/when_any/variadic_pass.cpp : when_any__variadic_p ] + ; + + #explicit ts_lock_guard ; + test-suite ts_lock_guard + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp : : lock_guard__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp : : lock_guard__cons__copy_ctor_f ] + [ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp : : lock_guard__lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp : : lock_guard__lock_compile_f ] + [ thread-safety-compile ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp : : lock_guard__adopt_lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp : : lock_guard__adopt_lock_compile_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp : lock_guard__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/default_pass.cpp : lock_guard__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/types_pass.cpp : lock_guard__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp : make_lock_guard_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp : make_lock_guard__adopt_lock_p ] + ; + + #explicit ts_unique_lock ; + test-suite ts_unique_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp : : unique_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp : : unique_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp : unique_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp : unique_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp : unique_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : uq_lk_cons_mv_c_upg_lk_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : uq_lk_cons_mv_c_upg_lk_t_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : uq_lk_cons_mv_c_upg_lk_f_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : uq_lk_cons_mv_c_upg_lk_u_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp : unique_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp : unique_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp : unique_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp : unique_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp : unique_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp : unique_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp : unique_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp : unique_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp : unique_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp : unique_lock__op_bool_p ] + #[ thread-compile-fail ./sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp : : unique_lock__op_int_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp : unique_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/types_pass.cpp : unique_lock__types_p ] + + + ; + + #explicit ts_make_unique_lock ; + test-suite ts_make_unique_lock + : + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp : make_unique_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp : make_unique_lock__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp : make_unique_lock__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp : make_unique_lock__try_to_lock_p ] + + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp : make_unique_locks__mutex_p ] + + ; + + #explicit ts_shared_lock ; + test-suite ts_shared_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp : : shared_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp : : shared_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp : shared_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : sh_lock_cons_move_ctor_unq_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : sh_lock_cons_move_ctor_upg_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp : shared_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp : shared_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp : shared_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp : shared_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp : shared_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp : shared_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp : shared_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp : shared_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp : shared_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp : shared_lock__op_bool_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp : shared_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/types_pass.cpp : shared_lock__types_p ] + + #[ thread-run2-h ./sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp : shared_lock__cons__default_p ] + #[ thread-run2-h ./sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp : shared_lock__cons__defer_lock_p ] + + ; + + #explicit ts_upgrade_lock ; + test-suite ts_upgrade_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp : : upgrade_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp : : upgrade_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp : upgrade_lock__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp : upgrade_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp : upgrade_lock__cons__defer_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upg_lock_cons_mv_ctor_uq_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp : upgrade_lock__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp : upgrade_lock__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp : upgrade_lock__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp : upgrade_lock__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp : upgrade_lock__unlock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp : upgrade_lock__member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp : upgrade_lock__non_member_swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp : upgrade_lock__release_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp : upgrade_lock__mutex_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp : upgrade_lock__op_bool_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp : upgrade_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp : upgrade_lock__types_p ] + ; + + #explicit ts_strict_lock ; + test-suite ts_strict_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp : : strict_lock__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp : : strict_lock__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/default_pass.cpp : strict_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp : strict_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/types_pass.cpp : strict_lock__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp : make_strict_lock_p ] + ; + + #explicit ts_nested_strict_lock ; + test-suite ts_nested_strict_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock_cons_copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock_cons_copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp : nested_strict_lock__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp : nested_strict_lock__owns_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp : nested_strict_lock__types_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp : make_nested_strict_lock_p ] + ; + + + #explicit ts_once ; + test-suite ts_once + : + #[ thread-compile-fail ./sync/mutual_exclusion/once/once_flag/assign_fail.cpp : : once_flag__assign_f ] + #[ thread-compile-fail ./sync/mutual_exclusion/once/once_flag/copy_fail.cpp : : once_flag__copy_f ] + #[ thread-run2-noit ./sync/mutual_exclusion/once/once_flag/default_pass.cpp : once_flag__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/once/call_once/call_once_pass.cpp : call_once_p ] + ; + + #explicit ts_mutex ; + test-suite ts_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/mutex/assign_fail.cpp : : mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/mutex/copy_fail.cpp : : mutex__copy_f ] + [ thread-safety-compile ./sync/mutual_exclusion/mutex/lock_compile_pass.cpp : : mutex__lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/lock_compile_fail.cpp : : mutex__lock_compile_f ] + # https://bugs.llvm.org/show_bug.cgi?id=32954 + # http://clang-developers.42468.n3.nabble.com/thread-safety-warnings-specifically-try-acquire-capability-td4059337.html + #[ thread-safety-compile ./sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp : : mutex__try_lock_compile_p ] + [ thread-safety-compile-fail ./sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp : : mutex__try_lock_compile_f ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/default_pass.cpp : mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/lock_pass.cpp : mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/mutex/native_handle_pass.cpp : mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/mutex/try_lock_pass.cpp : mutex__try_lock_p ] + ; + + #explicit ts_recursive_mutex ; + test-suite ts_recursive_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/assign_fail.cpp : : recursive_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/recursive_mutex/copy_fail.cpp : : recursive_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/default_pass.cpp : recursive_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/lock_pass.cpp : recursive_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp : recursive_mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp : recursive_mutex__try_lock_p ] + ; + + #explicit ts_recursive_timed_mutex ; + test-suite ts_recursive_timed_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp : : recursive_timed_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : rec_timed_mutex_native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : rec_timed_mutex_try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : rec_timed_mutex_try_lock_until_p ] + ; + + #explicit ts_timed_mutex ; + test-suite ts_timed_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/assign_fail.cpp : : timed_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/timed_mutex/copy_fail.cpp : : timed_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/default_pass.cpp : timed_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/lock_pass.cpp : timed_mutex__lock_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp : timed_mutex__native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp : timed_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp : timed_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp : timed_mutex__try_lock_until_p ] + ; + + #explicit ts_shared_mutex ; + test-suite ts_shared_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/assign_fail.cpp : : shared_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/shared_mutex/copy_fail.cpp : : shared_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/lock_pass.cpp : shared_mutex__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp : shared_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp : shared_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp : shared_mutex__try_lock_until_p ] + + #[ thread-run2-h ./sync/mutual_exclusion/shared_mutex/default_pass.cpp : shared_mutex__default_p ] + ; + + #explicit ts_null_mutex ; + test-suite ts_null_mutex + : + [ thread-compile-fail ./sync/mutual_exclusion/null_mutex/assign_fail.cpp : : null_mutex__assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/null_mutex/copy_fail.cpp : : null_mutex__copy_f ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/default_pass.cpp : null_mutex__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/lock_pass.cpp : null_mutex__lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp : null_mutex__try_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_pass.cpp : null_mutex__try_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp : null_mutex__try_lock_until_p ] + ; + + test-suite ts_sync_queue + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_queue/single_thread_pass.cpp : sync_queue__single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp : sync_queue__multi_thread_p ] + ; + + test-suite ts_sync_deque + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/single_thread_pass.cpp : sync_deque__single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp : sync_deque__multi_thread_p ] + ; + + test-suite ts_sync_bounded_queue + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_q_multi_thread_p ] + ; + + test-suite ts_sync_pq + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp : sync_pq_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp : sync_pq_multi_thread_p ] + ; + + test-suite ts_sync_tq + : + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp : sync_tq_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp : sync_tq_multi_thread_p ] + ; + + test-suite ts_scheduler + : + [ thread-run2-noit ./test_scheduled_tp.cpp : test_scheduled_tp_p ] + [ thread-run2-noit ./test_scheduling_adaptor.cpp : test_scheduling_adaptor_p ] + [ thread-run2-noit ./test_scheduler.cpp : test_scheduler_p ] + ; + + test-suite ts_queue_views + : + [ thread-run2-noit ./sync/mutual_exclusion/queue_views/single_thread_pass.cpp : queue_views__single_thread_p ] + #[ thread-run2-noit ./sync/mutual_exclusion/queue_views/multi_thread_pass.cpp : queue_views__multi_thread_p ] + ; + + test-suite ts_deque_views + : + [ thread-run2-noit ./sync/mutual_exclusion/deque_views/single_thread_pass.cpp : deque_views__single_thread_p ] + #[ thread-run2-noit ./sync/mutual_exclusion/deque_views/multi_thread_pass.cpp : deque_views__multi_thread_p ] + ; + + #explicit ts_this_thread ; + test-suite ts_this_thread + : + [ thread-run2-noit ./threads/this_thread/get_id/get_id_pass.cpp : this_thread__get_id_p ] + [ thread-run2-noit ./threads/this_thread/sleep_for/sleep_for_pass.cpp : this_thread__sleep_for_p ] + [ thread-run2-noit ./threads/this_thread/sleep_until/sleep_until_pass.cpp : this_thread__sleep_until_p ] + ; + + #explicit ts_thread ; + test-suite ts_thread + : + [ thread-compile-fail ./threads/thread/assign/copy_fail.cpp : : thread__assign__copy_f ] + [ thread-run2-noit ./threads/thread/assign/move_pass.cpp : thread__assign__move_p ] + [ thread-compile-fail ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_f ] + [ thread-run2-noit ./threads/thread/constr/default_pass.cpp : thread__constr__default_p ] + [ thread-run-lib2 ./threads/thread/constr/lambda_pass.cpp : thread__constr__lambda_p ] + [ thread-run-lib2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_p ] + [ thread-run-lib2 ./threads/thread/constr/FArgs_pass.cpp : thread__constr__FArgs_p ] + [ thread-run2-noit ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_p ] + [ thread-run2-noit ./threads/thread/constr/FrvalueArgs_pass.cpp : thread__constr__FrvalueArgs_p ] + [ thread-run2-noit ./threads/thread/constr/move_pass.cpp : thread__constr__move_p ] + [ thread-run2-noit ./threads/thread/destr/dtor_pass.cpp : thread__destr__dtor_p ] + [ thread-run2-noit ./threads/thread/id/hash_pass.cpp : thread__id__hash_p ] + [ thread-run2-noit ./threads/thread/members/detach_pass.cpp : thread__detach_p ] + [ thread-run2-noit ./threads/thread/members/get_id_pass.cpp : thread__get_id_p ] + [ thread-run2-noit ./threads/thread/members/join_pass.cpp : thread__join_p ] + [ thread-run2-noit ./threads/thread/members/try_join_until_pass.cpp : thread__join_until_p ] + [ thread-run2-noit ./threads/thread/members/try_join_for_pass.cpp : thread__join_for_p ] + [ thread-run2-noit ./threads/thread/members/joinable_pass.cpp : thread__joinable_p ] + [ thread-run2-noit ./threads/thread/members/native_handle_pass.cpp : thread__native_handle_p ] + [ thread-run2-noit ./threads/thread/members/swap_pass.cpp : thread__swap_p ] + [ thread-run2-noit ./threads/thread/non_members/swap_pass.cpp : swap_threads_p ] + [ thread-run2-noit ./threads/thread/static/hardware_concurrency_pass.cpp : thread__hardware_concurrency_p ] + ; + + #explicit ts_container ; + test-suite ts_container + : + [ thread-run2-noit ./threads/container/thread_vector_pass.cpp : container__thread_vector_p ] + [ thread-run2-noit ./threads/container/thread_ptr_list_pass.cpp : container__thread_ptr_list_p ] + ; + + explicit ts_examples_too_long ; + test-suite ts_examples_too_long + : + [ thread-run2 ../example/shared_mutex.cpp : ex_shared_mutex ] + ; + + #explicit ts_examples ; + test-suite ts_examples + : + [ thread-run2-noit ../example/monitor.cpp : ex_monitor ] + [ thread-compile ../example/starvephil.cpp : : ex_starvephil ] + [ thread-run2 ../example/tennis.cpp : ex_tennis ] + [ thread-compile ../example/condition.cpp : : ex_condition ] + [ thread-run2-noit ../example/mutex.cpp : ex_mutex ] + [ thread-run2-noit ../example/once.cpp : ex_once ] + [ thread-run2-noit ../example/recursive_mutex.cpp : ex_recursive_mutex ] + [ thread-run2-noit ../example/thread.cpp : ex_thread ] + [ thread-run2-noit ../example/thread_group.cpp : ex_thread_group ] + [ thread-run2-noit ../example/tss.cpp : ex_tss ] + [ thread-run2 ../example/xtime.cpp : ex_xtime ] + [ thread-run2 ../example/shared_monitor.cpp : ex_shared_monitor ] + #[ thread-run ../example/vhh_shared_monitor.cpp ] + #[ thread-run ../example/vhh_shared_mutex.cpp ] + [ thread-run2 ../example/make_future.cpp : ex_make_future ] + [ thread-run2 ../example/future_then.cpp : ex_future_then ] + [ thread-run2 ../example/future_fallback_to.cpp : ex_future_fallback_to ] + [ thread-run2 ../example/future_unwrap.cpp : ex_future_unwrap ] + [ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ] + [ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ] + [ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ] + [ thread-run2-noit ../example/std_thread_guard.cpp : ex_std_thread_guard : <toolset>gcc-4.8:<build>no ] + [ thread-run2-noit ../example/scoped_thread.cpp : ex_scoped_thread ] + [ thread-run2-noit ../example/std_scoped_thread.cpp : ex_std_scoped_thread : <toolset>gcc-4.8:<build>no ] + [ thread-run2-noit ../example/strict_lock.cpp : ex_strict_lock ] + [ thread-run2-noit ../example/ba_externallly_locked.cpp : ex_ba_externallly_locked ] + [ thread-run2 ../example/producer_consumer_bounded.cpp : ex_producer_consumer_bounded ] + [ thread-run2 ../example/producer_consumer.cpp : ex_producer_consumer ] + [ thread-run2 ../example/producer_consumer2.cpp : ex_producer_consumer2 ] + [ thread-run2 ../example/not_interleaved.cpp : ex_not_interleaved ] + [ thread-run2 ../example/lambda_future.cpp : ex_lambda_future ] + [ thread-run2 ../example/not_interleaved2.cpp : ex_not_interleaved2 ] + [ thread-run2 ../example/thread_pool.cpp : ex_thread_pool ] + [ thread-run2 ../example/user_scheduler.cpp : ex_user_scheduler ] + [ thread-run2 ../example/executor.cpp : ex_executor ] + [ thread-run2 ../example/generic_executor_ref.cpp : ex_generic_executor_ref ] + [ thread-run2 ../example/serial_executor.cpp : ex_serial_executor ] + #[ thread-run2 ../example/serial_executor_cont.cpp : ex_serial_executor_cont ] + [ thread-run2 ../example/future_when_all.cpp : ex_future_when_all ] + [ thread-run2 ../example/parallel_accumulate.cpp : ex_parallel_accumulate ] + [ thread-run2 ../example/parallel_quick_sort.cpp : ex_parallel_quick_sort ] + [ thread-run2 ../example/with_lock_guard.cpp : ex_with_lock_guard ] + [ thread-run2 ../example/fib_task_region.cpp : ex_fib_task_region ] + ; + + #explicit ts_shared_upwards ; + test-suite ts_shared_upwards + : + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_until_p ] + + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upg_lock_cons_move_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upg_lock_cons_move_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upg_lock_cons_move_ctor_sh_lock_untl_p ] + ; + + + #explicit ts_shared_lock_guard ; + test-suite ts_shared_lock_guard + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp : : shared_lock_guard__cons__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp : : shared_lock_guard__cons__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp : shared_lock_guard__cons__adopt_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp : shared_lock_guard__cons__default_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp : shared_lock_guard__types_p ] + ; + + #explicit ts_reverse_lock ; + test-suite ts_reverse_lock + : + [ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp : : reverse_lock__copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp : : reverse_lock__copy_ctor_f ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp : reverse_lock__unique_lock_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ] + ; + + + #explicit ts_synchronized_value ; + test-suite ts_synchronized_value + : + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp : synchronized_value__copy_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp : synchronized_value__copy_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp : synchronized_value__copy_T_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp : synchronized_value__copy_T_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp : synchronized_value__default_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/indirect_pass.cpp : synchronized_value__indirect_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp : synchronized_value__move_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp : synchronized_value__move_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp : synchronized_value__move_T_assign_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp : synchronized_value__move_T_ctor_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_pass.cpp : synchronized_value__swap_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp : synchronized_value__swap_T_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp : synchronized_value__synchronize_p ] + [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/call_pass.cpp : synchronized_value__call_p ] + + ; + + + test-suite ts_with_lock_guard + : + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp : with_lock_guard_simple_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp : with_lock_guard_bind_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp : with_lock_guard_move_p ] + [ thread-run2-noit ./sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp : with_lock_guard_lambda_p ] + ; + + explicit ts_invoke ; + test-suite ts_invoke + : + [ thread-run2-noit ./functional/invoke/invoke_int_0_pass.cpp : invoke_int_0_p ] + [ thread-run2-noit ./functional/invoke/invoke_lvalue_pass.cpp : invoke_lvalue_p ] + [ thread-run2-noit ./functional/invoke/invoke_rvalue_pass.cpp : invoke_rvalue_p ] + ; + + explicit ts_invoker ; + test-suite ts_invoker + : + [ thread-run2-noit ./functional/invoker/invoker_int_0_pass.cpp : invoker_int_0_p ] + [ thread-run2-noit ./functional/invoker/invoker_lvalue_pass.cpp : invoker_lvalue_p ] + [ thread-run2-noit ./functional/invoker/invoker_rvalue_pass.cpp : invoker_rvalue_p ] + ; + + + + explicit ts_more ; + test-suite ts_more + : + [ thread-run test_7666.cpp ] + [ thread-run test_7720.cpp ] + [ thread-run test_7755.cpp ] + [ thread-run test_8455.cpp ] + [ thread-run test_8508.cpp ] + #[ thread-run test_8557.cpp ] + [ thread-run test_8586.cpp ] + [ thread-run test_8943.cpp ] + [ thread-run test_8960.cpp ] + [ thread-run test_9079_a.cpp ] + [ thread-run test_9079_b.cpp ] + [ thread-run test_9192.cpp ] + #[ thread-run test_9303.cpp ] + #[ thread-run test_9720.cpp ] + #[ thread-run test_10125.cpp ] + #[ thread-run test_10128.cpp ] + #[ thread-run test_10340.cpp ] + ; + + explicit ts_more_cpp11 ; + test-suite ts_more_cpp11 + : + [ thread-run test_8596.cpp ] + [ thread-run test_8600.cpp ] + ; + + explicit perf ; + test-suite perf + : + #[ thread-run ../example/perf_condition_variable.cpp ] + #[ thread-run ../example/perf_shared_mutex.cpp ] + ; + + + #explicit ts_exception_list ; + test-suite ts_exception_list + : + [ thread-run2-noit ./experimental/parallel/v1/exception_list_pass.cpp : exception_list_p ] + ; + + #explicit ts_task_region ; + test-suite ts_task_region + : + [ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ] + ; + + explicit ts_other ; + test-suite ts_other + : + [ thread-run2 ../example/this_executor.cpp : ex_this_executor ] + [ thread-run2 ../example/default_executor.cpp : ex_default_executor ] + ; + + explicit ts_ ; + test-suite ts_ + : + #[ thread-run test_11256.cpp ] + #[ thread-run test_11256.cpp ] + #[ thread-run test_11499.cpp ] + #[ thread-run test_11611.cpp ] + #[ thread-run test_11818.cpp ] + #[ thread-run test_11796.cpp ] + #[ thread-run test_12293.cpp ] + #[ thread-run test_12949.cpp ] + #[ thread-run test_13480b.cpp ] + [ thread-run test_13561.cpp ] + + ; + + explicit test_time_jumps_1_obj ; + obj test_time_jumps_1_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + ; + + explicit test_time_jumps_2_obj ; + obj test_time_jumps_2_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + <define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + ; + + explicit test_time_jumps_3_obj ; + obj test_time_jumps_3_obj : test_time_jumps.cpp : + # BOOST_THREAD_USES_MOVE is required to prevent ambiguity between the two definitions + # of boost::move when using sync_priority_queue/sync_timed_queue with POD data types. + <define>BOOST_THREAD_USES_MOVE + <define>BOOST_THREAD_PROVIDES_FUTURE + <define>BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + <define>BOOST_THREAD_V2_SHARED_MUTEX + ; + + explicit test_time_jumps ; + test-suite test_time_jumps + : + [ exe test_time_jumps_1 : test_time_jumps_1_obj ../build//boost_thread ] + [ exe test_time_jumps_2 : test_time_jumps_2_obj ../build//boost_thread ] + [ exe test_time_jumps_3 : test_time_jumps_3_obj ../build//boost_thread ] + ; + + test-suite test_self_contained_headers : [ generate_self_contained_header_tests ] ; +} diff --git a/src/boost/libs/thread/test/condition_test_common.hpp b/src/boost/libs/thread/test/condition_test_common.hpp new file mode 100644 index 000000000..4aa114e05 --- /dev/null +++ b/src/boost/libs/thread/test/condition_test_common.hpp @@ -0,0 +1,97 @@ +#ifndef CONDITION_TEST_COMMON_HPP +#define CONDITION_TEST_COMMON_HPP +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_time.hpp> + +unsigned const timeout_seconds=5; + +struct wait_for_flag +{ + boost::mutex mutex; + boost::condition_variable cond_var; + bool flag; + unsigned woken; + + wait_for_flag(): + flag(false),woken(0) + {} + + struct check_flag + { + bool const& flag; + + check_flag(bool const& flag_): + flag(flag_) + {} + + bool operator()() const + { + return flag; + } + private: + void operator=(check_flag&); + }; + + + void wait_without_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + while(!flag) + { + cond_var.wait(lock); + } + ++woken; + } + + void wait_with_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + cond_var.wait(lock,check_flag(flag)); + if(flag) + { + ++woken; + } + } + + void timed_wait_without_predicate() + { + boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds); + + boost::unique_lock<boost::mutex> lock(mutex); + while(!flag) + { + if(!cond_var.timed_wait(lock,timeout)) + { + return; + } + } + ++woken; + } + + void timed_wait_with_predicate() + { + boost::system_time const timeout=boost::get_system_time()+boost::posix_time::seconds(timeout_seconds); + boost::unique_lock<boost::mutex> lock(mutex); + if(cond_var.timed_wait(lock,timeout,check_flag(flag)) && flag) + { + ++woken; + } + } + void relative_timed_wait_with_predicate() + { + boost::unique_lock<boost::mutex> lock(mutex); + if(cond_var.timed_wait(lock,boost::posix_time::seconds(timeout_seconds),check_flag(flag)) && flag) + { + ++woken; + } + } +}; + + +#endif diff --git a/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp b/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp new file mode 100644 index 000000000..de79412ae --- /dev/null +++ b/src/boost/libs/thread/test/experimental/parallel/v1/exception_list_pass.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2014 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) + +// <boost/thread/experimental/parallel/v1/exception_list.hpp> + + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/experimental/parallel/v1/exception_list.hpp> + +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp b/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp new file mode 100644 index 000000000..814ef28e5 --- /dev/null +++ b/src/boost/libs/thread/test/experimental/parallel/v2/task_region_pass.cpp @@ -0,0 +1,295 @@ +// Copyright (C) 2014-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) + +// <boost/thread/experimental/parallel/v1/exception_list.hpp> + + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/experimental/parallel/v2/task_region.hpp> +#include <string> + +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_NO_CXX11_LAMBDAS && defined(BOOST_THREAD_PROVIDES_INVOKE) +using boost::experimental::parallel::v2::task_region; +using boost::experimental::parallel::v2::task_region_handle; +using boost::experimental::parallel::v1::exception_list; + +void run_no_exception() +{ + std::string s("test"); + bool parent_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "parent" << std::endl; + }); + BOOST_TEST(parent_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); + BOOST_TEST(task3_flag); +} + +void run_no_exception_wait() +{ + std::string s("test"); + bool parent_flag = false; + bool wait_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "before" << std::endl; + trh.wait(); + wait_flag = true; + std::cout << "parent" << std::endl; + }); + BOOST_TEST(parent_flag); + BOOST_TEST(wait_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); + BOOST_TEST(task3_flag); +} + +void run_exception_1() +{ + try + { + task_region([](task_region_handle& trh) + { + trh.run([]() + { + std::cout << "task1" << std::endl; + throw 1; + }); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + trh.run([]() + { + std::cout << "task3" << std::endl; + }); +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + BOOST_TEST(false); +#endif + }); + BOOST_TEST(false); + } + catch (exception_list const& e) + { + BOOST_TEST_EQ(e.size(), 1u); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void run_exception() +{ + try + { + task_region([](task_region_handle& trh) + { + trh.run([]() + { + std::cout << "task1" << std::endl; + throw 1; + }); + trh.run([]() + { + std::cout << "task2" << std::endl; + throw 2; + }); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + trh.run([]() + { + std::cout << "task3" << std::endl; + throw 3; + }); + std::cout << "parent" << std::endl; + throw 100; + }); + BOOST_TEST(false); + } + catch (exception_list const& el) + { + BOOST_TEST(el.size() >= 1u); + for (boost::exception_ptr const& e: el) + { + try { + boost::rethrow_exception(e); + } + catch (boost::exception&) + { + BOOST_TEST(true); + } + catch (int i) // this doesn't works yet + { + BOOST_TEST((i == 1) || (i == 2) || (i == 3)); + } + catch (...) + { + BOOST_TEST(false); + } + } + } + catch (...) + { + BOOST_TEST(false); + } +} + + +void run_nested_exception() +{ + std::string s("test"); + bool parent_flag = false; + bool task1_flag = false; + bool task2_flag = false; + bool task21_flag = false; + bool task3_flag = false; + try + { + task_region([&](task_region_handle& trh) + { + parent_flag = true; + trh.run([&]() + { + task1_flag = true; + std::cout << "task1: " << s << std::endl; + }); + trh.run([&]() + { + task2_flag = true; + std::cout << "task2" << std::endl; + task_region([&](task_region_handle& trh) + { + trh.run([&]() + { + task21_flag = true; + std::cout << "task2.1" << std::endl; + throw 21; + }); + }); + }); + int i = 0, j = 10, k = 20; + trh.run([=, &task3_flag]() + { + task3_flag = true; + std::cout << "task3: " << i << " " << j << " " << k << std::endl; + }); + std::cout << "parent" << std::endl; + }); + } + catch (exception_list const& el) + { + BOOST_TEST(el.size() == 1u); + for (boost::exception_ptr const& e: el) + { + try { + boost::rethrow_exception(e); + } + catch (int i) // this doesn't works yet + { + BOOST_TEST_EQ(i, 21); + } + catch (boost::exception&) + { + BOOST_TEST(true); + } + catch (...) + { + BOOST_TEST(false); + } + } + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(parent_flag); + BOOST_TEST(task1_flag); + BOOST_TEST(task2_flag); + BOOST_TEST(task21_flag); +} + + +int main() +{ + run_no_exception(); + run_no_exception_wait(); + run_exception(); + run_exception_1(); + run_nested_exception(); + return boost::report_errors(); +} +#else +int main() +{ + return boost::report_errors(); +} +#endif diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp new file mode 100644 index 000000000..fa1f67543 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_int_0_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int f() +{ + return 1; +} + +struct A_int_0 +{ + A_int_0() + { + } + int operator()() + { + return 4; + } + int operator()() const + { + return 5; + } +}; + + +int main() +{ + const A_int_0 ca; + A_int_0 a; + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST_EQ(boost::detail::invoke(f), 1); + BOOST_TEST_EQ(boost::detail::invoke(&f), 1); + BOOST_TEST_EQ(boost::detail::invoke(A_int_0()), 4); + BOOST_TEST_EQ(boost::detail::invoke(a), 4); + BOOST_TEST_EQ(boost::detail::invoke(ca), 5); +#endif + + BOOST_TEST_EQ(boost::detail::invoke<int>(f), 1); + BOOST_TEST_EQ(boost::detail::invoke<int>(&f), 1); + BOOST_TEST_EQ(A_int_0()(), 4); +#if defined BOOST_THREAD_PROVIDES_INVOKE || ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 4); +#else + //BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 5); +#endif + BOOST_TEST_EQ(a(), 4); + BOOST_TEST_EQ(boost::detail::invoke<int>(a), 4); + BOOST_TEST_EQ(ca(), 5); + BOOST_TEST_EQ(boost::detail::invoke<int>(ca), 5); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp new file mode 100644 index 000000000..154953d89 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_lvalue_pass.cpp @@ -0,0 +1,336 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + int i = 2; + boost::detail::invoke(f_void_1, i); + BOOST_TEST(count == save_count + 2); + save_count = count; + } +#endif + { + int i = 2; + boost::detail::invoke<void>(f_void_1, i); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke<void>(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoke<void>(fp, i); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + A_void_1 a0; + int i = 4; + boost::detail::invoke(a0, i); + BOOST_TEST(count == save_count+4); + save_count = count; + } +#endif + { + A_void_1 a0; + int i = 4; + boost::detail::invoke<void>(a0, i); + BOOST_TEST(count == save_count+4); + save_count = count; + } + // member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + boost::detail::invoke(fp, a); + BOOST_TEST(count == save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke(fp, ap); + BOOST_TEST(count == save_count+1); + save_count = count; + } +#endif + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + boost::detail::invoke<void>(fp, a); + BOOST_TEST(count == save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke<void>(fp, ap); + BOOST_TEST(count == save_count+1); + save_count = count; + } + // const member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoke(fp, a); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke(fp, ap); + BOOST_TEST(count == save_count+2); + save_count = count; + } +#endif + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoke<void>(fp, a); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoke<void>(fp, ap); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + int i = 2; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(f_int_1, i) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(f_int_1, i) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + int i = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(fp, i) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(fp, i) == 4); + } + // functor + { + int i = 4; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(A_int_1(), i) == 3); +#endif + const A_int_1 ca; + A_int_1 a; + BOOST_TEST(boost::detail::invoke<int>(a, i) == 3); + //BOOST_TEST(boost::detail::invoke<int>(ca, i) == 3); +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke<int>(A_int_1(), i) == 3); +#endif + } + // member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, a) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, a) == 3); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, ap) == 3); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, ap) == 3); + } + // const member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, A_int_1()) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, A_int_1()) == 4); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, ap) == 4); +#endif + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, ap) == 4); + } + // member data pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 5); + + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 5); + +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_int_1* ap = &a; + + boost::detail::invoke(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 6); + + boost::detail::invoke<int>(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 6); + +#endif + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, ap) == 6); + boost::detail::invoke(&A_int_1::data_, ap) = 7; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, ap) == 7); + + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 7); + boost::detail::invoke<int>(&A_int_1::data_, ap) = 8; + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 8); +#endif + + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + int i = 2; + int j = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; +#endif + boost::detail::invoke<void>(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + int j = 3; + boost::detail::invoke(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif +// A_void_2 a2; +// boost::detail::invoke<void>(&A_void_2::mem1, a2, j); +// BOOST_TEST(count == save_count+3); +// save_count = count; + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp new file mode 100644 index 000000000..82ea09432 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoke/invoke_rvalue_pass.cpp @@ -0,0 +1,227 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/detail/invoke.hpp> + +#include <boost/thread/detail/invoke.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_1, 2); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer + { + void (*fp)(int) = f_void_1; + boost::detail::invoke(fp, 3); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor + { + A_void_1 a0; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(a0, 4); + BOOST_TEST(count == save_count+4); + save_count = count; +#endif + boost::detail::invoke<void>(a0, 4); + BOOST_TEST(count == save_count+4); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + void (A_void_1::*fp)() = &A_void_1::mem1; + boost::detail::invoke(fp, A_void_1()); + BOOST_TEST(count == save_count+1); + save_count = count; + //BUG + boost::detail::invoke<void>(fp, A_void_1()); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_void_1 a; + boost::detail::invoke(fp, &a); + BOOST_TEST(count == save_count+1); + save_count = count; + //BUG + boost::detail::invoke<int>(fp, &a); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + } + // const member function pointer + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + boost::detail::invoke(fp, A_void_1()); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1 a; + boost::detail::invoke(fp, &a); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + BOOST_TEST(boost::detail::invoke(f_int_1, 2) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + BOOST_TEST(boost::detail::invoke(fp, 3) == 4); + } + // functor + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(A_int_1(), 4) == 3); + BOOST_TEST(boost::detail::invoke<int>(A_int_1(), 4) == 3); +#endif + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, A_int_1()) == 3); + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, A_int_1()) == 3); +#endif + + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::mem1, &a) == 3); + } + // const member function pointer + { + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, A_int_1()) == 4); + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::mem2, &a) == 4); + } + // member data pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, A_int_1()) == 5); + BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, A_int_1()) == 5); + A_int_1 a; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 5); + boost::detail::invoke(&A_int_1::data_, a) = 6; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, a) == 6); + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, &a) == 6); + boost::detail::invoke(&A_int_1::data_, &a) = 7; + BOOST_TEST(boost::detail::invoke(&A_int_1::data_, &a) == 7); +#endif + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_2, 2, 3); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif + + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp new file mode 100644 index 000000000..123bde2e6 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_int_0_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/detail/invoker.hpp> + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int f() +{ + return 1; +} + +struct A_int_0 +{ + A_int_0() + { + } + int operator()() + { + return 4; + } + int operator()() const + { + return 5; + } +}; + + +int main() +{ + const A_int_0 ca; + A_int_0 a; + +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST_EQ(boost::detail::invoker<int(*)()>(f)(), 1); + BOOST_TEST_EQ(boost::detail::invoker<int(*)()>(&f)(), 1); + BOOST_TEST_EQ(boost::detail::invoker<A_int_0>(A_int_0())(), 4); + BOOST_TEST_EQ(boost::detail::invoker<A_int_0>(a)(), 4); + BOOST_TEST_EQ(boost::detail::invoker<const A_int_0>(ca)(), 5); +#endif + + //BOOST_TEST_EQ(boost::detail::invoker<int>(f), 1); + //BOOST_TEST_EQ(boost::detail::invoker<int>(&f), 1); + BOOST_TEST_EQ(A_int_0()(), 4); +#if defined BOOST_THREAD_PROVIDES_INVOKE || ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + //BOOST_TEST_EQ(boost::detail::invoker<int>(A_int_0()), 4); +#else + //BOOST_TEST_EQ(boost::detail::invoke<int>(A_int_0()), 5); +#endif + //BOOST_TEST_EQ(a(), 4); + //BOOST_TEST_EQ(boost::detail::invoke<int>(a), 4); + //BOOST_TEST_EQ(ca(), 5); + //BOOST_TEST_EQ(boost::detail::invoke<int>(ca), 5); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp new file mode 100644 index 000000000..42a98d45a --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_lvalue_pass.cpp @@ -0,0 +1,342 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/detail/invoker.hpp> + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + typedef void result_type; + void operator()(int i) + { + count += i; + } + + void mem1() { + std::cout << "mem1 " << count << std::endl; + ++count; + std::cout << "mem1 " << count << std::endl; + } + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + int i = 2; + boost::detail::invoker<void(*)(int), int>(f_void_1, i)(); + BOOST_TEST(count == save_count + 2); + save_count = count; + } +#endif +// { +// int i = 2; +// boost::detail::invoke<void>(f_void_1, i); +// BOOST_TEST(count == save_count + 2); +// save_count = count; +// } + // function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoker<void(*)(int), int>(fp, i)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif +// { +// void (*fp)(int) = f_void_1; +// int i = 3; +// boost::detail::invoke<void>(fp, i); +// BOOST_TEST(count == save_count+3); +// save_count = count; +// } +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (*fp)(int) = f_void_1; + int i = 3; + boost::detail::invoker<void(*)(int), int>(fp, i)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } +#endif +// { +// void (*fp)(int) = f_void_1; +// int i = 3; +// boost::detail::invoke<void>(fp, i); +// BOOST_TEST(count == save_count+3); +// save_count = count; +// } + // functor +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + A_void_1 a0; + int i = 4; + boost::detail::invoker<A_void_1, int>(a0, i)(); + BOOST_TEST(count == save_count+4); + save_count = count; + } +#endif +// { +// A_void_1 a0; +// int i = 4; +// boost::detail::invoke<void>(a0, i); +// BOOST_TEST(count == save_count+4); +// save_count = count; +// } + // member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() = &A_void_1::mem1; + A_void_1 a; + //BUG + boost::detail::invoker<void (A_void_1::*)(), A_void_1>(fp, a)(); + BOOST_TEST_EQ(count, save_count+1); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoker<void (A_void_1::*)(), A_void_1*>(fp, ap)(); + BOOST_TEST_EQ(count, save_count+1); + save_count = count; + } +#endif +// { +// void (A_void_1::*fp)() = &A_void_1::mem1; +// A_void_1 a; +// boost::detail::invoke<void>(fp, a); +// BOOST_TEST(count == save_count+1); +// save_count = count; +// A_void_1* ap = &a; +// boost::detail::invoke<void>(fp, ap); +// BOOST_TEST(count == save_count+1); +// save_count = count; +// } + // const member function pointer +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1>(fp, a)(); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1* ap = &a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1*>(fp, ap)(); + BOOST_TEST_EQ(count, save_count+2); + save_count = count; + } +#endif +// { +// void (A_void_1::*fp)() const = &A_void_1::mem2; +// A_void_1 a; +// boost::detail::invoke<void>(fp, a); +// BOOST_TEST(count == save_count+2); +// save_count = count; +// A_void_1* ap = &a; +// boost::detail::invoke<void>(fp, ap); +// BOOST_TEST(count == save_count+2); +// save_count = count; +// } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + int i = 2; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int(*)(int), int>(f_int_1, i)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(f_int_1, i) == 3); + } + // function pointer + { + int (*fp)(int) = f_int_1; + int i = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(fp, i)() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(fp, i) == 4); + } + // functor + { + int i = 4; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<A_int_1, int>(A_int_1(), i)() == 3)); +#endif +// const A_int_1 ca; +// A_int_1 a; +// BOOST_TEST(boost::detail::invoke<int>(a, i) == 3); +// //BOOST_TEST(boost::detail::invoke<int>(ca, i) == 3); +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST(boost::detail::invoke<int>(A_int_1(), i) == 3); +//#endif + } + // member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1>(&A_int_1::mem1, a)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, a) == 3); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1*>(&A_int_1::mem1, ap)() == 3)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, ap) == 3); + } + // const member function pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1>(&A_int_1::mem2, A_int_1())() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, A_int_1()) == 4); + A_int_1* ap = &a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1*>(&A_int_1::mem2, ap)() == 4)); +#endif +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem2, ap) == 4); + } + // member data pointer + { + A_int_1 a; +#if defined BOOST_THREAD_PROVIDES_INVOKE + // BUG + //BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) == 5); + +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 5); + +#endif +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// A_int_1* ap = &a; +// +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) = 6; +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a) == 6); +// +//// boost::detail::invoke<int>(&A_int_1::data_, a) = 6; +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, a) == 6); +// +//#endif +// +//#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) == 6); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) = 7; +// BOOST_TEST(boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, ap) == 7); +// +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 7); +//// boost::detail::invoke<int>(&A_int_1::data_, ap) = 8; +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, ap) == 8); +//#endif + + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + int i = 2; + int j = 3; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(f_void_2, i, j); + BOOST_TEST(count == save_count+5); + save_count = count; +#endif +// boost::detail::invoke<void>(f_void_2, i, j); +// BOOST_TEST(count == save_count+5); +// save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + int j = 3; + boost::detail::invoke(&A_void_2::mem1, A_void_2(), j); + BOOST_TEST(count == save_count+3); + save_count = count; + +// boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), j); +// BOOST_TEST(count == save_count+3); +// save_count = count; +#endif +// A_void_2 a2; +// boost::detail::invoke<void>(&A_void_2::mem1, a2, j); +// BOOST_TEST(count == save_count+3); +// save_count = count; + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp b/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp new file mode 100644 index 000000000..ae06e16b6 --- /dev/null +++ b/src/boost/libs/thread/test/functional/invoker/invoker_rvalue_pass.cpp @@ -0,0 +1,230 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/detail/invoker.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +//#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/detail/invoker.hpp> +#include <boost/detail/lightweight_test.hpp> + +int count = 0; + +// 1 arg, return void + +void f_void_1(int i) +{ + count += i; +} + +struct A_void_1 +{ + typedef void result_type; + void operator()(int i) + { + count += i; + } + + void mem1() {++count;} + void mem2() const {count += 2;} +}; + +void +test_void_1() +{ + int save_count = count; + // function + { + boost::detail::invoker<void(*)(int), int>(f_void_1, 2)(); + BOOST_TEST(count == save_count + 2); + save_count = count; + } + // function pointer + { + void (*fp)(int) = f_void_1; + boost::detail::invoker<void(*)(int), int>(fp, 3)(); + BOOST_TEST(count == save_count+3); + save_count = count; + } + // functor + { + A_void_1 a0; +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoker<A_void_1, int>(a0, 4)(); + BOOST_TEST(count == save_count+4); + save_count = count; +#endif +// boost::detail::invoke<void>(a0, 4); +// BOOST_TEST(count == save_count+4); +// save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + void (A_void_1::*fp)() = &A_void_1::mem1; + boost::detail::invoker<void (A_void_1::*)(), A_void_1>(fp, A_void_1())(); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + // boost::detail::invoke<void>(fp, A_void_1()); + // BOOST_TEST(count == save_count+1); + // save_count = count; +#if defined BOOST_THREAD_PROVIDES_INVOKE + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)(), A_void_1*>(fp, &a)(); + BOOST_TEST(count == save_count+1); + save_count = count; + +#endif + // boost::detail::invoke<int>(fp, &a); + // BOOST_TEST(count == save_count+1); + // save_count = count; + } + // const member function pointer + { + void (A_void_1::*fp)() const = &A_void_1::mem2; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1>(fp, A_void_1())(); + BOOST_TEST(count == save_count+2); + save_count = count; + A_void_1 a; + boost::detail::invoker<void (A_void_1::*)() const, A_void_1*>(fp, &a)(); + BOOST_TEST(count == save_count+2); + save_count = count; + } +} + +// 1 arg, return int + +int f_int_1(int i) +{ + return i + 1; +} + +struct A_int_1 +{ + A_int_1() : data_(5) {} + int operator()(int i) + { + return i - 1; + } + + int mem1() {return 3;} + int mem2() const {return 4;} + int data_; +}; + +void +test_int_1() +{ + // function + { + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(f_int_1, 2)() == 3)); + } + // function pointer + { + int (*fp)(int) = f_int_1; + BOOST_TEST((boost::detail::invoker<int (*)(int), int>(fp, 3)() == 4)); + } + // functor + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<A_int_1, int>(A_int_1(), 4)() == 3)); +// BOOST_TEST(boost::detail::invoke<int>(A_int_1(), 4) == 3); +#endif + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(),A_int_1>(&A_int_1::mem1, A_int_1())() == 3)); +// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::mem1, A_int_1()) == 3); +#endif + + A_int_1 a; + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)(), A_int_1*>(&A_int_1::mem1, &a)() == 3)); + } + // const member function pointer + { + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1>(&A_int_1::mem2, A_int_1())() == 4)); + A_int_1 a; + BOOST_TEST((boost::detail::invoker<int (A_int_1::*)() const, A_int_1*>(&A_int_1::mem2, &a)() == 4)); + } + // member data pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, A_int_1())() == 5)); +//// BOOST_TEST(boost::detail::invoke<int>(&A_int_1::data_, A_int_1()) == 5); +// A_int_1 a; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() == 5)); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() = 6; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, a)() == 6)); +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() == 6)); +// boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() = 7; +// BOOST_TEST((boost::detail::invoker<int A_int_1::*>(&A_int_1::data_, &a)() == 7)); +#endif + } +} + +// 2 arg, return void + +void f_void_2(int i, int j) +{ + count += i+j; +} + +struct A_void_2 +{ + void operator()(int i, int j) + { + count += i+j; + } + + void mem1(int i) {count += i;} + void mem2(int i) const {count += i;} +}; + +void +test_void_2() +{ + int save_count = count; + // function + { + boost::detail::invoke(f_void_2, 2, 3); + BOOST_TEST(count == save_count+5); + save_count = count; + } + // member function pointer + { +#if defined BOOST_THREAD_PROVIDES_INVOKE + boost::detail::invoke(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; + + boost::detail::invoke<void>(&A_void_2::mem1, A_void_2(), 3); + BOOST_TEST(count == save_count+3); + save_count = count; +#endif + + } +} + +int main() +{ + test_void_1(); + test_int_1(); + test_void_2(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp b/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp new file mode 100644 index 000000000..1922bb7dc --- /dev/null +++ b/src/boost/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void do_nothing() +{} + +void test() +{ + boost::thread t1(do_nothing); + boost::thread t2; + t2=t1; +} + +#include "./remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp b/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp new file mode 100644 index 000000000..63522f0f0 --- /dev/null +++ b/src/boost/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void do_nothing() +{} + +void test() +{ + boost::thread t1(do_nothing); + boost::thread t2(t1); +} + +#include "./remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp b/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp new file mode 100644 index 000000000..1f43f2a2e --- /dev/null +++ b/src/boost/libs/thread/test/remove_error_code_unused_warning.hpp @@ -0,0 +1,17 @@ +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/thread.hpp> + +void remove_unused_warning() +{ + //../../../boost/system/error_code.hpp:214:36: warning: 'boost::system::posix_category' defined but not used [-Wunused-variable] + //../../../boost/system/error_code.hpp:215:36: warning: 'boost::system::errno_ecat' defined but not used [-Wunused-variable] + //../../../boost/system/error_code.hpp:216:36: warning: 'boost::system::native_ecat' defined but not used [-Wunused-variable] + + //(void)boost::system::posix_category; + //(void)boost::system::errno_ecat; + //(void)boost::system::native_ecat; + +} diff --git a/src/boost/libs/thread/test/self_contained_header.cpp b/src/boost/libs/thread/test/self_contained_header.cpp new file mode 100644 index 000000000..ef4117a13 --- /dev/null +++ b/src/boost/libs/thread/test/self_contained_header.cpp @@ -0,0 +1,26 @@ +/* + * Copyright Andrey Semashev 2019. + * 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) + */ +/*! + * \file self_contained_header.cpp + * \author Andrey Semashev + * \date 2019-01-19 + * + * \brief This file contains a test boilerplate for checking that every public header is self-contained and does not have any missing #includes. + */ + +#if defined(BOOST_THREAD_TEST_POST_WINDOWS_H) +#include <windows.h> +#endif + +#define BOOST_THREAD_TEST_INCLUDE_HEADER() <boost/thread/BOOST_THREAD_TEST_HEADER> + +#include BOOST_THREAD_TEST_INCLUDE_HEADER() + +int main(int, char*[]) +{ + return 0; +} diff --git a/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp b/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp new file mode 100644 index 000000000..4d9a31ca5 --- /dev/null +++ b/src/boost/libs/thread/test/shared_mutex_locking_thread.hpp @@ -0,0 +1,145 @@ +#ifndef SHARED_MUTEX_LOCKING_THREAD_HPP +#define SHARED_MUTEX_LOCKING_THREAD_HPP + +// (C) Copyright 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/shared_mutex.hpp> + +template<typename lock_type> +class locking_thread +{ + boost::shared_mutex& rw_mutex; + unsigned& unblocked_count; + boost::condition_variable& unblocked_condition; + unsigned& simultaneous_running_count; + unsigned& max_simultaneous_running; + boost::mutex& unblocked_count_mutex; + boost::mutex& finish_mutex; +public: + locking_thread(boost::shared_mutex& rw_mutex_, + unsigned& unblocked_count_, + boost::mutex& unblocked_count_mutex_, + boost::condition_variable& unblocked_condition_, + boost::mutex& finish_mutex_, + unsigned& simultaneous_running_count_, + unsigned& max_simultaneous_running_): + rw_mutex(rw_mutex_), + unblocked_count(unblocked_count_), + unblocked_condition(unblocked_condition_), + simultaneous_running_count(simultaneous_running_count_), + max_simultaneous_running(max_simultaneous_running_), + unblocked_count_mutex(unblocked_count_mutex_), + finish_mutex(finish_mutex_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + locking_thread(locking_thread const&) = default; +#endif + + void operator()() + { + // acquire lock + lock_type lock(rw_mutex); + + // increment count to show we're unblocked + { + boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex); + ++unblocked_count; + unblocked_condition.notify_one(); + ++simultaneous_running_count; + if(simultaneous_running_count>max_simultaneous_running) + { + max_simultaneous_running=simultaneous_running_count; + } + } + + // wait to finish + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + { + boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex); + --simultaneous_running_count; + } + } +private: + void operator=(locking_thread&); +}; + +class simple_writing_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_writing_thread&); + +public: + simple_writing_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_writing_thread(simple_writing_thread const&) = default; +#endif + + void operator()() + { + boost::unique_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + +class simple_reading_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_reading_thread&); + +public: + simple_reading_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_reading_thread(simple_reading_thread const&) = default; +#endif + + void operator()() + { + boost::shared_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + + +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp new file mode 100644 index 000000000..703616ff1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable& operator=(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> + +void fail() +{ + boost::condition_variable cv0; + boost::condition_variable cv1; + cv1 = cv0; + +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp new file mode 100644 index 000000000..374ce3165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::condition_variable cv0; + boost::condition_variable cv1(cv0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp new file mode 100644 index 000000000..465a12de8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/default_pass.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::condition_variable cv0; + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp new file mode 100644 index 000000000..533898ed4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/dtor_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable* cv; +boost::mutex m; +typedef boost::unique_lock<boost::mutex> Lock; + +bool f_ready = false; +bool g_ready = false; + +void f() +{ + Lock lk(m); + f_ready = true; + cv->notify_one(); + cv->wait(lk); + delete cv; +} + +void g() +{ + Lock lk(m); + g_ready = true; + cv->notify_one(); + while (!f_ready) + { + cv->wait(lk); + } + cv->notify_one(); +} + +int main() +{ + cv = new boost::condition_variable; + boost::thread th2(g); + Lock lk(m); + while (!g_ready) + { + cv->wait(lk); + } + lk.unlock(); + boost::thread th1(f); + th1.join(); + th2.join(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp new file mode 100644 index 000000000..79dbcd295 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/lost_notif_pass.cpp @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2017 Austin J. Beer +// +// 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +// Summary of each test: +// 1. Start the test thread and wait for it to start up. +// The test thread waits for the flag to be set using a large timeout. +// 2. The main thread takes the lock and then sleeps for a long time while holding +// the lock before setting the flag and calling notify_one(). If the wait +// function being tested is polling pthread_cond_timedwait() internally, any +// notifications sent after pthread_cond_timedwait() times out but before it can +// reacquire the lock may be "lost". pthread_cond_timedwait() will report that +// it timed out and the wait function may incorrectly assume that no +// notification was received. This test ensures that that doesn't happen. +// 3. Measure how it takes the test thread to return. If it received the +// notification, it will return fairly quickly. If it missed the notification, +// the test thread won't return until the wait function being tested times out. + +//------------------------------------------------------------------------------ + +boost::condition_variable cv; +boost::mutex mut; + +bool flag; +bool waiting; + +bool flagIsSet() +{ + return flag; +} + +bool threadIsWaiting() +{ + return waiting; +} + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_DATETIME + +boost::posix_time::milliseconds posix_wait_time(1000); + +template <typename F> +void test_posix_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time(); + + BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void timed_wait_absolute_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time); + } +} + +void timed_wait_absolute_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void timed_wait_relative_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, posix_wait_time); + } +} + +void timed_wait_relative_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, posix_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_CHRONO + +boost::chrono::milliseconds chrono_wait_time(1000); + +template <typename F> +void test_chrono_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now(); + + BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void wait_until_system_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time); + } +} + +void wait_until_system_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_until_steady_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time); + } +} + +void wait_until_steady_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_for_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_for(lk, chrono_wait_time); + } +} + +void wait_for_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_for(lk, chrono_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +int main() +{ +#ifdef BOOST_THREAD_USES_DATETIME + test_posix_wait_function(timed_wait_absolute_without_pred); + test_posix_wait_function(timed_wait_absolute_with_pred); + test_posix_wait_function(timed_wait_relative_without_pred); + test_posix_wait_function(timed_wait_relative_with_pred); +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + test_chrono_wait_function(wait_until_system_without_pred); + test_chrono_wait_function(wait_until_system_with_pred); + test_chrono_wait_function(wait_until_steady_without_pred); + test_chrono_wait_function(wait_until_steady_with_pred); + test_chrono_wait_function(wait_for_without_pred); + test_chrono_wait_function(wait_for_with_pred); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp new file mode 100644 index 000000000..9835f5920 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> + +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE + //BOOST_STATIC_ASSERT((boost::is_same<boost::condition_variable::native_handle_type, pthread_cond_t*>::value)); + boost::condition_variable cv; + boost::condition_variable::native_handle_type h = cv.native_handle(); + BOOST_TEST(h != 0); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp new file mode 100644 index 000000000..4c6a0af3e --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::steady_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::nanoseconds nanoseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + milliseconds(250); + while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + } + else + { + nanoseconds d = t1 - t0 - milliseconds(250); + std::cout << "diff= " << d.count() << std::endl; + std::cout << "max_diff= " << max_diff.count() << std::endl; + assert( d < max_diff); + assert(test2 == 0); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + BOOST_TEST(false); + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + return boost::report_errors(); +} +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp new file mode 100644 index 000000000..92ba82f1e --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_for_pred_pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock < boost::mutex > lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + cv.wait_for(lk, milliseconds(250), Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + } + else + { + assert(t1 - t0 - milliseconds(250) < max_diff); + assert(test2 == 0); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp new file mode 100644 index 000000000..612724b85 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// void wait(unique_lock<mutex>& lock); + + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + while (test2 == 0) { + cv.wait(lk); + } + assert(test2 != 0); + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try { + boost::unique_lock<boost::mutex>lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + { + cv.wait(lk); + } + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + return boost::report_errors(); +} +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp new file mode 100644 index 000000000..34ef32268 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pass.cpp @@ -0,0 +1,128 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include <cassert> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +boost::condition_variable cv; +boost::mutex mut; + + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock < boost::mutex > lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + assert(test2 != 0); + } + else + { + ns d = t1 - t0 - Clock::duration(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + assert(test2 == 0); + } + ++runs; + } catch(...) { + assert(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } +} + +int main() +{ + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + test1 = 0; + test2 = 0; + try + { + boost::unique_lock < boost::mutex > lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp new file mode 100644 index 000000000..120e49853 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable/wait_until_pred_pass.cpp @@ -0,0 +1,146 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> +#include <iostream> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::nanoseconds nanoseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable cv; +boost::mutex mut; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + try { + boost::unique_lock<boost::mutex> lk(mut); + assert(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + bool r = cv.wait_until(lk, t, Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + assert(t1 - t0 < max_diff); + assert(test2 != 0); + assert(r); + } + else + { + const nanoseconds d = t1 - t0 - milliseconds(250); + std::cout << "diff= " << d.count() << std::endl; + std::cout << "max_diff= " << max_diff.count() << std::endl; + assert(d < max_diff); + assert(test2 == 0); + assert(!r); + } + ++runs; + } catch(...) { + std::cout << "ERROR exception" << __LINE__ << std::endl; + assert(false); + } +} + +int main() +{ + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + test1 = 0; + test2 = 0; + try + { + boost::unique_lock<boost::mutex> lk(mut); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } catch(...) { + BOOST_TEST(false); + std::cout << "ERROR exception" << __LINE__ << std::endl; + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp new file mode 100644 index 000000000..6dba459cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any& operator=(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> + +void fail() +{ + boost::condition_variable_any cv0; + boost::condition_variable_any cv1; + cv1 = cv0; +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp new file mode 100644 index 000000000..71d3a3f06 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::condition_variable_any cv0; + boost::condition_variable_any cv1(cv0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp new file mode 100644 index 000000000..21116ebc4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/default_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::condition_variable_any cv0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp new file mode 100644 index 000000000..7734d93b7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/dtor_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable_any* cv; +boost::timed_mutex m; +typedef boost::unique_lock<boost::timed_mutex> Lock; + +bool f_ready = false; +bool g_ready = false; + +void f() +{ + Lock lk(m); + f_ready = true; + cv->notify_one(); + cv->wait(lk); + delete cv; +} + +void g() +{ + Lock lk(m); + g_ready = true; + cv->notify_one(); + while (!f_ready) + { + cv->wait(lk); + } + cv->notify_one(); +} + +int main() +{ + cv = new boost::condition_variable_any; + boost::thread th2(g); + Lock lk(m); + while (!g_ready) + { + cv->wait(lk); + } + lk.unlock(); + boost::thread th1(f); + th1.join(); + th2.join(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp new file mode 100644 index 000000000..c696da3c2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/lost_notif_pass.cpp @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2017 Austin J. Beer +// +// 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) + +// <boost/thread/condition_variable> + +// class condition_variable; + +// condition_variable(const condition_variable&) = delete; + +#include <iostream> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +// Summary of each test: +// 1. Start the test thread and wait for it to start up. +// The test thread waits for the flag to be set using a large timeout. +// 2. The main thread takes the lock and then sleeps for a long time while holding +// the lock before setting the flag and calling notify_one(). If the wait +// function being tested is polling pthread_cond_timedwait() internally, any +// notifications sent after pthread_cond_timedwait() times out but before it can +// reacquire the lock may be "lost". pthread_cond_timedwait() will report that +// it timed out and the wait function may incorrectly assume that no +// notification was received. This test ensures that that doesn't happen. +// 3. Measure how it takes the test thread to return. If it received the +// notification, it will return fairly quickly. If it missed the notification, +// the test thread won't return until the wait function being tested times out. + +//------------------------------------------------------------------------------ + +boost::condition_variable_any cv; +boost::mutex mut; + +bool flag; +bool waiting; + +bool flagIsSet() +{ + return flag; +} + +bool threadIsWaiting() +{ + return waiting; +} + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_DATETIME + +boost::posix_time::milliseconds posix_wait_time(1000); + +template <typename F> +void test_posix_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::universal_time(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time(); + + BOOST_TEST(t1 - t0 < boost::posix_time::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void timed_wait_absolute_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time); + } +} + +void timed_wait_absolute_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, boost::posix_time::microsec_clock::universal_time() + posix_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void timed_wait_relative_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.timed_wait(lk, posix_wait_time); + } +} + +void timed_wait_relative_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.timed_wait(lk, posix_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_DATETIME not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +#ifdef BOOST_THREAD_USES_CHRONO + +boost::chrono::milliseconds chrono_wait_time(1000); + +template <typename F> +void test_chrono_wait_function(F f) +{ + flag = false; + waiting = false; + boost::thread t(f); + while (!threadIsWaiting()) + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(1)); + } + + boost::unique_lock<boost::mutex> lk(mut); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + boost::chrono::steady_clock::time_point t0 = boost::chrono::steady_clock::now(); + flag = true; + cv.notify_one(); + lk.unlock(); + t.join(); + boost::chrono::steady_clock::time_point t1 = boost::chrono::steady_clock::now(); + + BOOST_TEST(t1 - t0 < boost::chrono::milliseconds(250)); +} + +//------------------------------------------------------------------------------ + +void wait_until_system_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time); + } +} + +void wait_until_system_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::system_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_until_steady_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time); + } +} + +void wait_until_steady_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_until(lk, boost::chrono::steady_clock::now() + chrono_wait_time, flagIsSet); +} + +//------------------------------------------------------------------------------ + +void wait_for_without_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + while (!flagIsSet()) + { + cv.wait_for(lk, chrono_wait_time); + } +} + +void wait_for_with_pred() +{ + boost::unique_lock<boost::mutex> lk(mut); + waiting = true; + cv.wait_for(lk, chrono_wait_time, flagIsSet); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + +//------------------------------------------------------------------------------ + +int main() +{ +#ifdef BOOST_THREAD_USES_DATETIME + test_posix_wait_function(timed_wait_absolute_without_pred); + test_posix_wait_function(timed_wait_absolute_with_pred); + test_posix_wait_function(timed_wait_relative_without_pred); + test_posix_wait_function(timed_wait_relative_with_pred); +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + test_chrono_wait_function(wait_until_system_without_pred); + test_chrono_wait_function(wait_until_system_with_pred); + test_chrono_wait_function(wait_until_steady_without_pred); + test_chrono_wait_function(wait_until_steady_with_pred); + test_chrono_wait_function(wait_for_without_pred); + test_chrono_wait_function(wait_for_with_pred); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp new file mode 100644 index 000000000..b1fca89f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + milliseconds(250); + while (test2 == 0 && cv.wait_for(lk, t - Clock::now()) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp new file mode 100644 index 000000000..3885b23c1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_for_pred_pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +typedef boost::chrono::system_clock Clock; +typedef boost::chrono::milliseconds milliseconds; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + cv.wait_for(lk, milliseconds(250), Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp new file mode 100644 index 000000000..acf5fb1c4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout) {} + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp new file mode 100644 index 000000000..f6e9b7ee2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/condition_variable_any/wait_until_pred_pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable_any> + +// class condition_variable_any; + +// condition_variable_any(const condition_variable_any&) = delete; + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +struct Clock +{ + typedef boost::chrono::milliseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<Clock> time_point; + static const bool is_steady = true; + + static time_point now() + { + using namespace boost::chrono; + return time_point(duration_cast<duration> (steady_clock::now().time_since_epoch())); + } +}; + +class Pred +{ + int& i_; +public: + explicit Pred(int& i) : + i_(i) + { + } + + bool operator()() + { + return i_ != 0; + } +}; + +boost::condition_variable_any cv; + +typedef boost::timed_mutex L0; +typedef boost::unique_lock<L0> L1; + +L0 m0; + +int test1 = 0; +int test2 = 0; + +int runs = 0; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + L1 lk(m0); + BOOST_TEST(test2 == 0); + test1 = 1; + cv.notify_one(); + Clock::time_point t0 = Clock::now(); + Clock::time_point t = t0 + Clock::duration(250); + bool r = cv.wait_until(lk, t, Pred(test2)); + Clock::time_point t1 = Clock::now(); + if (runs == 0) + { + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 != 0); + BOOST_TEST(r); + } + else + { + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(test2 == 0); + BOOST_TEST(!r); + } + ++runs; +} + +int main() +{ + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + test2 = 1; + lk.unlock(); + cv.notify_one(); + t.join(); + } + test1 = 0; + test2 = 0; + { + L1 lk(m0); + boost::thread t(f); + BOOST_TEST(test1 == 0); + while (test1 == 0) + cv.wait(lk); + BOOST_TEST(test1 != 0); + lk.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp b/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp new file mode 100644 index 000000000..becac4da5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/cv_status/cv_status_pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// static unsigned hardware_concurrency(); + +#include <boost/thread/condition_variable.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + BOOST_TEST(boost::cv_status::no_timeout != boost::cv_status::timeout); + } + { + boost::cv_status st = boost::cv_status::no_timeout; + BOOST_TEST(st == boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout==st); + BOOST_TEST(st != boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout!=st); + } + { + boost::cv_status st = boost::cv_status::timeout; + BOOST_TEST(st == boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout==st); + BOOST_TEST(st != boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout!=st); + } + { + boost::cv_status st; + st = boost::cv_status::no_timeout; + BOOST_TEST(st == boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout==st); + BOOST_TEST(st != boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout!=st); + } + { + boost::cv_status st; + st = boost::cv_status::timeout; + BOOST_TEST(st == boost::cv_status::timeout); + BOOST_TEST(boost::cv_status::timeout==st); + BOOST_TEST(st != boost::cv_status::no_timeout); + BOOST_TEST(boost::cv_status::no_timeout!=st); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp new file mode 100644 index 000000000..d6eecbd95 --- /dev/null +++ b/src/boost/libs/thread/test/sync/conditions/notify_all_at_thread_exit_pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/condition_variable.hpp> + +// void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); + +#define BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_VESRION 3 + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::condition_variable cv; +boost::mutex mut; + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::high_resolution_clock Clock; + +void func() +{ + boost::unique_lock < boost::mutex > lk(mut); + boost::notify_all_at_thread_exit(cv, boost::move(lk)); + boost::this_thread::sleep_for(ms(300)); +} + +int main() +{ + boost::unique_lock < boost::mutex > lk(mut); + boost::thread(func).detach(); + Clock::time_point t0 = Clock::now(); + cv.wait(lk); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(t1 - t0 > ms(250)); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp new file mode 100644 index 000000000..d5a0f4423 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/async/async_executor_pass.cpp @@ -0,0 +1,250 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// template <class Executor, class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(Executor& ex, F&& f, Args&&... args); + +#define BOOST_THREAD_VERSION 5 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include <iostream> +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <memory> +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef boost::chrono::milliseconds ms; + +class A +{ + long data_; + +public: + typedef long result_type; + + explicit A(long i) : + data_(i) + { + } + + long doit() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } + long operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } +}; + +class MoveOnly +{ +public: + typedef int result_type; + + int value; + +BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + value = 0; + } + MoveOnly( BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 1; + } + MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 2; + return *this; + } + + int operator()() + { + boost::this_thread::sleep_for(ms(200)); + return 3; + } + template <typename OS> + friend OS& operator<<(OS& os, MoveOnly const& v) + { + os << v.value; + return os; + } + }; + + namespace boost + { +BOOST_THREAD_DCL_MOVABLE (MoveOnly) + } + +int f0() +{ + boost::this_thread::sleep_for(ms(200)); + return 3; +} + +int i = 0; + +int& f1() +{ + boost::this_thread::sleep_for(ms(200)); + return i; +} + +void f2() +{ + boost::this_thread::sleep_for(ms(200)); +} + +boost::csbl::unique_ptr<int> f3_0() +{ + boost::this_thread::sleep_for(ms(200)); + boost::csbl::unique_ptr<int> r( (new int(3))); + return boost::move(r); +} +MoveOnly f3_1() +{ + boost::this_thread::sleep_for(ms(200)); + MoveOnly r; + return boost::move(r); +} + +boost::csbl::unique_ptr<int> f3(int i) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::csbl::unique_ptr<int>(new int(i)); +} + +boost::csbl::unique_ptr<int> f4( + BOOST_THREAD_RV_REF_BEG boost::csbl::unique_ptr<int> BOOST_THREAD_RV_REF_END p +) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::move(p); +} + +struct check_timer { + boost::chrono::nanoseconds delay; + Clock::time_point start; + check_timer(boost::chrono::nanoseconds delay) + : delay(delay) + , start(Clock::now()) + { + } + ~check_timer() { + Clock::time_point now = Clock::now(); + BOOST_TEST(now - start < delay); + std::cout << __FILE__ << "[" << __LINE__ << "] " << (now - start).count() << std::endl; + } + +}; + +int main() +{ + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + boost::future<int> f = boost::async(ex, &f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && defined BOOST_THREAD_PROVIDES_EXECUTORS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + boost::future<long> f = boost::async(ex, A(3)); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && defined BOOST_THREAD_PROVIDES_EXECUTORS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::executor_adaptor<boost::basic_thread_pool> ex(1); + MoveOnly mo; + boost::future<int> f = boost::async(ex, boost::move(mo)); + //boost::future<int> f = boost::async(ex, MoveOnly()); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp b/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp new file mode 100644 index 000000000..86fdfdbec --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/async/async_pass.cpp @@ -0,0 +1,903 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// template <class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(F&& f, Args&&... args); + +// template <class F, class... Args> +// future<typename result_of<F(Args...)>::type> +// async(launch policy, F&& f, Args&&... args); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#include <iostream> +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> +#include <memory> +#include <boost/detail/lightweight_test.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef boost::chrono::milliseconds ms; + +class A +{ + long data_; + +public: + typedef long result_type; + + explicit A(long i) : + data_(i) + { + } + + long doit() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } + long operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return data_; + } +}; + +class MoveOnly +{ +public: + typedef int result_type; + + int value; + + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + value = 0; + } + MoveOnly( BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 1; + } + MoveOnly& operator=(BOOST_THREAD_RV_REF(MoveOnly)) + { + value = 2; + return *this; + } + + int operator()() const + { + boost::this_thread::sleep_for(ms(200)); + return 3; + } + template <typename OS> + friend OS& operator<<(OS& os, MoveOnly const& v) + { + os << v.value; + return os; + } +}; + +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE (MoveOnly) +} + +int f0() +{ + boost::this_thread::sleep_for(ms(200)); + return 3; +} + +int i = 0; + +int& f1() +{ + boost::this_thread::sleep_for(ms(200)); + return i; +} + +void f2() +{ + boost::this_thread::sleep_for(ms(200)); +} + +boost::csbl::unique_ptr<int> f3_0() +{ + boost::this_thread::sleep_for(ms(200)); + boost::csbl::unique_ptr<int> r( (new int(3))); + return boost::move(r); +} +MoveOnly f3_1() +{ + boost::this_thread::sleep_for(ms(200)); + MoveOnly r; + return boost::move(r); +} + +boost::csbl::unique_ptr<int> f3(int i) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::csbl::unique_ptr<int>(new int(i)); +} + +boost::csbl::unique_ptr<int> f4( + BOOST_THREAD_RV_REF_BEG boost::csbl::unique_ptr<int> BOOST_THREAD_RV_REF_END p +) +{ + boost::this_thread::sleep_for(ms(200)); + return boost::move(p); +} + +struct check_timer { + boost::chrono::nanoseconds delay; + Clock::time_point start; + check_timer(boost::chrono::nanoseconds delay) + : delay(delay) + , start(Clock::now()) + { + } + ~check_timer() { + Clock::time_point now = Clock::now(); + BOOST_TEST(now - start < delay); + std::cout << __FILE__ << "[" << __LINE__ << "] " << (now - start).count() << std::endl; + } + +}; + +int main() +{ + { + try { + boost::async(f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + { + try { + boost::async(boost::launch::async, f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try { + boost::async(boost::launch::deferred, f0); + } catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::shared_future<int> f = boost::async(f0).share(); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::async, f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<long> f = boost::async(boost::launch::async, A(3)); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<long> f = boost::async(boost::launch::deferred, A(3)); + //boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + A a(3); + boost::future<long> f = boost::async(boost::launch::async, &A::doit, &a); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + A a(3); + boost::future<long> f = boost::async(boost::launch::deferred, &A::doit, &a); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly())); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::deferred, BOOST_THREAD_MAKE_RV_REF(MoveOnly())); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::any, f0); + boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<int> f = boost::async(boost::launch::deferred, f0); + //boost::this_thread::sleep_for(ms(300)); + int res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::async, f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::any, f1); + boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<int&> f = boost::async(boost::launch::deferred, f1); + //boost::this_thread::sleep_for(ms(300)); + int* res; + { + check_timer timer(ms(500)); + res = &f.get(); + } + BOOST_TEST(res == &i); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::async, f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::any, f2); + boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<void> f = boost::async(boost::launch::deferred, f2); + //boost::this_thread::sleep_for(ms(300)); + { + check_timer timer(ms(500)); + f.get(); + } + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f = boost::async(&f3_1); + boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST_EQ(res.value, 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f = boost::async(boost::launch::deferred, &f3_1); + //boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST_EQ(res.value, 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<MoveOnly> f; + f = boost::async(&f3_1); + boost::this_thread::sleep_for(ms(300)); + MoveOnly res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(res.value == 2); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f3_0); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::async, &f3, 3); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f3, 3); + //boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f3, 3); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::async, &f4, boost::csbl::unique_ptr<int>(new int(3))); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(boost::launch::deferred, &f4, boost::csbl::unique_ptr<int>(new int(3))); + //boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<std::endl; + { + try + { + boost::future<boost::csbl::unique_ptr<int> > f = boost::async(&f4, boost::csbl::unique_ptr<int>(new int(3))); + boost::this_thread::sleep_for(ms(300)); + boost::csbl::unique_ptr<int> res; + { + check_timer timer(ms(500)); + res = f.get(); + } + BOOST_TEST(*res == 3); + } + catch (std::exception& ex) + { + std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl; + BOOST_TEST(false && "exception thrown"); + } + catch (...) + { + BOOST_TEST(false && "exception thrown"); + } + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp new file mode 100644 index 000000000..b400074cd --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/async_deferred_then_pass.cpp @@ -0,0 +1,153 @@ +// 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + +int p1() +{ + BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + try + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + { + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + } + BOOST_TEST(! f1.valid()); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(boost::launch::deferred, p1).then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, p1); + boost::future<int> f21 = f1.then(&p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::deferred, p1); + boost::future<int> f2= f1.then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(boost::launch::deferred, p1).then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp new file mode 100644 index 000000000..170f3a057 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/copy_assign_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// future& operator=(const future&) = delete; + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = p.get_future(); + boost::future<T> f; + f = f0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp new file mode 100644 index 000000000..3a16afd50 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/copy_ctor_fail.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class future<R> + +// future(const future&) = delete; + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = p.get_future(); + boost::future<T> f = f0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp new file mode 100644 index 000000000..1b4cf392f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/default_pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::future<int> f; + BOOST_TEST(!f.valid()); + } + { + boost::future<int&> f; + BOOST_TEST(!f.valid()); + } + { + boost::future<void> f; + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp new file mode 100644 index 000000000..abfca7d8c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/dtor_pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// ~future(); + +#define BOOST_THREAD_VERSION 3 +#include <boost/exception/exception.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp new file mode 100644 index 000000000..7db938d37 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/get_or_pass.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// R future::get_or(R&&); +// R& future<R&>::get_or(R&); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/core/ref.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get_or(4) == 3); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<T> f = p.get_future(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + try + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.get_or(4) == 4); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (...) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(!f.valid()); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int& T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + int k=4; + BOOST_TEST(f.get_or(boost::ref(k)) == 5); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + int j=4; + BOOST_TEST(f.get_or(boost::ref(j)) == 4); + } + catch (...) + { + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp new file mode 100644 index 000000000..ec2ccf8b0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/get_pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// const R& future::get(); +// R& future<R&>::get(); +// void future<void>::get(); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + boost::future<T> f = p.get_future(); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + try + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(f.get() == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (boost::wrap<int> const& i) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(i.value == 3); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + catch (...) + { + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + BOOST_TEST(!f.valid()); +#endif + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef int& T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 5); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<double> const& i) + { + BOOST_TEST(i.value == 3.5); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + boost::exception_ptr ptr = f.get_exception_ptr(); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + typedef void T; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + p.set_value(); +#endif + BOOST_TEST(f.valid()); + f.get(); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func6, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(4)); +#endif + try + { + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 4); + } + catch (...) + { + BOOST_TEST(false); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + BOOST_TEST(!f.valid()); +#endif + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp new file mode 100644 index 000000000..ebb13e5e0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/move_assign_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class future<R> + +// future& operator=(future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp new file mode 100644 index 000000000..8da893a3c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/move_ctor_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class future<R> + +// future(future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp new file mode 100644 index 000000000..91c07f5cd --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/share_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// shared_future<R> share() &&; + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + typedef int T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::future<T> f0; + boost::shared_future<T> sf = f0.share(); + boost::shared_future<T> f = sf; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.cpp new file mode 100644 index 000000000..0ea37bd7f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_deferred_pass.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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +#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; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + assert(f.is_ready()); + + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(boost::launch::deferred, &p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(boost::launch::deferred, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(boost::launch::deferred, &p2); + boost::future<int> f2= f21.then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(boost::launch::deferred, &p2).then(boost::launch::deferred, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp new file mode 100644 index 000000000..fcb062a0e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_executor_pass.cpp @@ -0,0 +1,152 @@ +// 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 5 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cassert> + +#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; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + assert(f.is_ready()); + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(ex, &p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(ex, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).then(ex, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(ex, &p2); + boost::future<int> f2= f21.then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(ex, &p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(&p2).then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).then(ex, &p2).then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp new file mode 100644 index 000000000..12270679b --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/then_pass.cpp @@ -0,0 +1,133 @@ +// 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#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; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG; + return; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(! f1.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f21 = f1.then(&p2); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f1 = boost::async(p1); + boost::future<int> f2= f1.then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).then(&p2).then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp new file mode 100644 index 000000000..71bca7abe --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_for_pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// future_status +// wait_for(const chrono::duration<Rep, Period>& rel_time) const; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> +#include "../../../timming.hpp" + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp new file mode 100644 index 000000000..daa9b376f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// void wait() const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + func3(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + func5(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp new file mode 100644 index 000000000..e9351671d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/future/wait_until_pass.cpp @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template <class Rep, class Period> +// future_status +// wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp new file mode 100644 index 000000000..dfce3cde7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/make_ready_future_pass.cpp @@ -0,0 +1,157 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// future<void> make_ready_future(); +// template <class T> +// future<decay_t<T>> make_ready_future(T&&); +// template <class T> +// future<T> make_ready_future(remove_reference_t<T>&); +// template <class T> +// future<T> make_ready_future(remove_reference_t<T>&&); +// template <class T, class ...Args> +// future<T> make_ready_future(Args&& ... args); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + A(int i, int j) : + value(i+j) + { + } + int value; +}; + +A make(int i) { + return A(i); +} +A make(int i, int j) { + return A(i, j); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + movable2(int i, int j) : value_(i+j){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == true)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == false)); +#endif + + { + boost::future<void> f = boost::make_ready_future(); + f.wait(); + } + { + typedef A T; + T i; + boost::future<T> f = boost::make_ready_future(i); + BOOST_TEST(f.get().value==0); + } +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(); + BOOST_TEST(f.get().value==0); + } + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(1); + BOOST_TEST(f.get().value==1); + } + { + typedef A T; + boost::future<T> f = boost::make_ready_future<T>(1,2); + BOOST_TEST(f.get().value==3); + } + { + typedef A T; + T i; + boost::future<T&> f = boost::make_ready_future<T&>(i); + BOOST_TEST(f.get().value==0); + } +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// sync/futures/make_ready_future_pass.cpp:125:65: erreur: conversion from Ôboost::future<boost::rv<movable2> >Õ to non-scalar type Ôboost::future<movable2>Õ requested + { + typedef movable2 T; + T i; + boost::future<T> f = boost::make_ready_future(boost::move(i)); + BOOST_TEST_EQ(f.get().value(),1); + } +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(); + BOOST_TEST(f.get().value()==1); + } + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(1); + BOOST_TEST(f.get().value()==1); + } + { + typedef movable2 T; + boost::future<T> f = boost::make_ready_future<T>(1,2); + BOOST_TEST(f.get().value()==3); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp new file mode 100644 index 000000000..e83c06446 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/alloc_ctor_pass.cpp @@ -0,0 +1,181 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// template <class F, class Allocator> +// explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +double fct() +{ + return 5.0; +} +long lfct() +{ + return 5; +} + +class A +{ + long data_; + +public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(A) + static int n_moves; + static int n_copies; + static int n_instances; + static int n_destroy; + + explicit A(long i) : data_(i) + { + ++n_instances; + } + A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_) + { + ++n_instances; + ++n_moves; BOOST_THREAD_RV(a).data_ = -1; + } + A& operator=(BOOST_THREAD_RV_REF(A) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + A(const A& a) : data_(a.data_) + { + ++n_instances; + ++n_copies; + } + A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~A() + { + --n_instances; + ++n_destroy; + } + + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int A::n_moves = 0; +int A::n_copies = 0; +int A::n_instances = 0; +int A::n_destroy = 0; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + BOOST_TEST(A::n_copies == 0); + BOOST_TEST(A::n_moves > 0); + BOOST_TEST(A::n_instances == 0); + BOOST_TEST(A::n_destroy > 0); + BOOST_TEST(test_alloc_base::count == 0); + A::n_copies = 0; + A::n_moves = 0; + { + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), a); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + //BOOST_TEST(A::n_copies > 0); + //BOOST_TEST(A::n_moves > 0); + BOOST_TEST(test_alloc_base::count == 0); + A::n_copies = 0; + A::n_moves = 0; + { + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), a); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + //BOOST_TEST(A::n_copies > 0); + //BOOST_TEST(A::n_moves > 0); + BOOST_TEST(test_alloc_base::count == 0); + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), fct); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::allocator_arg, + test_allocator<A>(), &lfct); + BOOST_TEST(test_alloc_base::count > 0); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp new file mode 100644 index 000000000..7f068eced --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_assign_fail.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task& operator=(packaged_task&) = delete; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = p0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp new file mode 100644 index 000000000..22a174961 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/copy_ctor_fail.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task(packaged_task&) = delete; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(p0); + + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp new file mode 100644 index 000000000..7ab9f1e7c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/default_ctor_pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// packaged_task(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE int() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE int +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <string> + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + BOOST_TEST(!p.valid()); + + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp new file mode 100644 index 000000000..89620ad05 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/dtor_pass.cpp @@ -0,0 +1,108 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// ~packaged_task(); + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +void func(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> ) +{ +} + +void func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif +} + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func, boost::move(p)).detach(); +#else + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>* p2=new boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>(boost::move(p)); + delete p2; +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + std::cout << __LINE__ << std::endl; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p(); +#endif + std::cout << __LINE__ << std::endl; + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + std::cout << __LINE__ << std::endl; + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp new file mode 100644 index 000000000..a4bd3105f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp @@ -0,0 +1,378 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// template <class F> +// explicit packaged_task(F&& f); + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE void +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void(int) +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void() +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#define BOOST_THREAD_DETAIL_VOID_SIGNATURE_2 void +#endif + +void void_fct() +{ + return; +} +double fct() +{ + return 5.0; +} +long lfct() +{ + return 5; +} + +class A +{ +public: + long data_; + + static int n_moves; + static int n_copies; + BOOST_THREAD_COPYABLE_AND_MOVABLE(A) + static void reset() + { + n_moves=0; + n_copies=0; + } + + explicit A(long i) : data_(i) + { + } + A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + A& operator=(BOOST_THREAD_RV_REF(A) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + A(const A& a) : data_(a.data_) + { + ++n_copies; + } + A& operator=(BOOST_THREAD_COPY_ASSIGN_REF(A) a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~A() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int A::n_moves = 0; +int A::n_copies = 0; + +class M +{ + +public: + long data_; + static int n_moves; + + BOOST_THREAD_MOVABLE_ONLY(M) + static void reset() { + n_moves=0; + } + explicit M(long i) : data_(i) + { + } + M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + M& operator=(BOOST_THREAD_RV_REF(M) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + ~M() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int M::n_moves = 0; + +class C +{ +public: + long data_; + + static int n_copies; + static void reset() + { + n_copies=0; + } + + explicit C(long i) : data_(i) + { + } + C(const C& a) : data_(a.data_) + { + ++n_copies; + } + C& operator=(C const& a) + { + data_ = a.data_; + ++n_copies; + return *this; + } + ~C() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; +int C::n_copies = 0; + +int main() +{ + { + A::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + BOOST_TEST(A::n_copies == 0); + BOOST_TEST_EQ(A::n_moves, 1); + } + { + A::reset(); + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } + { + A::reset(); + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + A::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(A(5))); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST(A::n_copies == 0); + BOOST_TEST_EQ(A::n_moves, 1); + } + { + A::reset(); + A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } + { + A::reset(); + const A a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(A::n_copies, 1); + BOOST_TEST_EQ(A::n_moves, 0); + } +#endif + { + M::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5))); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES); + BOOST_TEST_EQ(M::n_moves, 1); + } + { + M::reset(); + M a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::move(a)); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(M::n_moves, 1); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + M::reset(); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5))); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(M::n_moves, 1); + } + { + M::reset(); + M a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(boost::move(a)); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(M::n_moves, 1); + } +#endif + { + C::reset(); + C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(C::n_copies, 1); + } + + { + C::reset(); + const C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + BOOST_TEST_EQ(C::n_copies, 1); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + C::reset(); + C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(C::n_copies, 1); + } + + { + C::reset(); + const C a(5); + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE_2> p(a); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(1); + BOOST_TEST_EQ(C::n_copies, 1); + } +#endif + { + boost::packaged_task<BOOST_THREAD_DETAIL_VOID_SIGNATURE> p(void_fct); + BOOST_TEST(p.valid()); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p(); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(fct); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(&lfct); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp new file mode 100644 index 000000000..7b2985794 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/get_future_pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// future<R> get_future(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::future_already_retrieved)); + } + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + try + { + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp new file mode 100644 index 000000000..08db7bbf2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp @@ -0,0 +1,189 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// packaged_task(packaged_task&& other); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO && \ + defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && \ + defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +class E : public std::exception +{ +public: + long data; + explicit E(long i) : + data(i) + { + } + + const char* what() const throw() { return ""; } + + ~E() throw() {} +}; +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()(long i, long j) const + { + if (j == 'z') BOOST_THROW_EXCEPTION( E(6) ); + return data_ + i + j; + } +}; + +void func0_mv(BOOST_THREAD_RV_REF(boost::packaged_task<double(int, char)>) p) +//void func0(boost::packaged_task<double(int, char)> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.make_ready_at_thread_exit(3, 'a'); +} +void func0(boost::packaged_task<double(int, char)> *p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p->make_ready_at_thread_exit(3, 'a'); +} +void func1(boost::packaged_task<double(int, char)> *p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p->make_ready_at_thread_exit(3, 'z'); +} + +void func2(boost::packaged_task<double(int, char)> *p) +{ + p->make_ready_at_thread_exit(3, 'a'); + try + { + p->make_ready_at_thread_exit(3, 'c'); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } +} + +void func3(boost::packaged_task<double(int, char)> *p) +{ + try + { + p->make_ready_at_thread_exit(3, 'a'); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +} + +int main() +{ + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + boost::thread(func0_mv, boost::move(p)).detach(); +#else + boost::thread(func0, &p).detach(); +#endif + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func0, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); + //boost::thread(func1, boost::move(p)).detach(); + boost::thread(func1, &p).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func1, &p).detach(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + } + { + boost::packaged_task<double(int, char)> p(A(5)); + boost::future<double> f = p.get_future(); + //boost::thread(func2, boost::move(p)).detach(); + boost::thread(func2, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::future<double> f = p2.get_future(); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread(func2, &p).detach(); + BOOST_TEST(f.get() == 105.0); + } + { + boost::packaged_task<double(int, char)> p(A(5)); + //boost::thread t(func3, boost::move(p)); + boost::thread t(func3, &p); + t.join(); + } + { + boost::packaged_task<double(int, char)> p2(A(5)); + boost::packaged_task<double(int, char)> p = boost::move(p2); + boost::thread t(func3, &p); + t.join(); + } + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +//#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp new file mode 100644 index 000000000..fe3c062f8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/member_swap_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// void swap(packaged_task& other); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + return data_; + } + long operator()(long i, long j) const + { + return data_ + i + j; + } +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp new file mode 100644 index 000000000..fe696c8fb --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/move_assign_pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class promise<R> + +// promise& operator=(promise&& rhs); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + // p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp new file mode 100644 index 000000000..a5085b311 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/move_ctor_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R> + +// packaged_task(packaged_task&& other); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p = boost::move(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp new file mode 100644 index 000000000..fb579094d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/non_member_swap_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// template <class R> +// void +// swap(packaged_task<R>& x, packaged_task<R>& y); + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : data_(i) {} + + long operator()() const {return data_;} + long operator()(long i, long j) const {return data_ + i + j;} +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0(A(5)); + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(p.valid()); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p0; + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + p.swap(p0); + BOOST_TEST(!p0.valid()); + BOOST_TEST(!p.valid()); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp new file mode 100644 index 000000000..db932f72b --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/operator_pass.cpp @@ -0,0 +1,218 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// void operator()(); + + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double(int, char) +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 + 3 +'a' +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double() +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +#else +#define BOOST_THREAD_DETAIL_SIGNATURE_2 double +#define BOOST_THREAD_DETAIL_SIGNATURE_2_RES 5 +#endif +class E : public std::exception +{ +public: + long data; + explicit E(long i) : + data(i) + { + } + + const char* what() const throw() { return ""; } + + ~E() throw() {} +}; + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + if (data_ == 0) BOOST_THROW_EXCEPTION(E(6)); + return data_; + } + long operator()(long i, long j) const + { + if (j == 'z') BOOST_THROW_EXCEPTION(E(6)); + return data_ + i + j; + } + ~A() {} +}; + +void func0(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif +} + +void func1(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'z'); +#else + p(); +#endif +} + +void func2(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'c'); +#else + p(); +#endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } +} + +void func3(boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p) +{ + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); +#else + p(); +#endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +} + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func0, boost::move(p)).detach(); +#else + //p(); +#endif + //BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(0)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + try + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + p(); +#endif + f.get(); + BOOST_TEST(false); + } + catch (const E& e) + { + BOOST_TEST(e.data == 6); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread t(func2, boost::move(p)); +#else + p(); +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + BOOST_TEST(f.get() == 105); + t.join(); +#else + BOOST_TEST(f.get() == 5.0); +#endif + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread t(func3, boost::move(p)); + t.join(); +#else + try + { + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + p(3, 'a'); + #else + p(); + #endif + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } +#endif + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp new file mode 100644 index 000000000..711e7a57f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/reset_pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class packaged_task<R> + +// void operator()(); + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +class A +{ + long data_; + +public: + explicit A(long i) : + data_(i) + { + } + + long operator()() const + { + return data_; + } + long operator()(long i, long j) const + { + if (j == 'z') throw A(6); + return data_ + i + j; + } +}; + +int main() +{ + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(A(5)); + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + //p(3, 'a'); + p(); + BOOST_TEST(f.get() == 5.0); + p.reset(); + //p(4, 'a'); + p(); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.get() == 5.0); + } + { + boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p; + try + { + p.reset(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp new file mode 100644 index 000000000..a52fb0439 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/types_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// template<class R, class... ArgTypes> +// class packaged_task<R(ArgTypes...)> +// { +// public: +// typedef R result_type; + + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct A {}; + +int main() +{ + //BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::packaged_task<A>::result_type, A>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp b/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp new file mode 100644 index 000000000..ef75b7caa --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/packaged_task/use_allocator_pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class packaged_task<R(ArgTypes...)> + +// template <class Callable, class Alloc> +// struct uses_allocator<packaged_task<Callable>, Alloc> +// : true_type { }; + + +#define BOOST_THREAD_VERSION 4 +#if BOOST_THREAD_VERSION == 4 +#define BOOST_THREAD_DETAIL_SIGNATURE double() +#else +#define BOOST_THREAD_DETAIL_SIGNATURE double +#endif + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE>, test_allocator<double> >::value), ""); + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp new file mode 100644 index 000000000..0d0c3c0b9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(allocator_arg_t, const Allocator& a); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int&> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p(boost::allocator_arg, test_allocator<void>()); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp new file mode 100644 index 000000000..07895578f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/copy_assign_fail.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class promise<R> +// promise& operator=(const promise& rhs) = delete; + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<int> p0; + boost::promise<int> p; + p = p0; + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp new file mode 100644 index 000000000..cfd67a6d7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/copy_ctor_fail.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class promise<R> +// promise& operator=(const promise& rhs) = delete; + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<int> p0; + boost::promise<int> p(p0); + } + + return boost::report_errors(); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp new file mode 100644 index 000000000..00198a168 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/default_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::promise<int> p; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + { + boost::promise<int&> p; + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + { + boost::promise<void> p; + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp new file mode 100644 index 000000000..e449c0378 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/dtor_pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// ~promise(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(3); + } + BOOST_TEST(f.get() == 3); + } + { + typedef int T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + //T i = + (void)f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + typedef int& T; + int i = 4; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(i); + } + BOOST_TEST(&f.get() == &i); + } + { + typedef int& T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + //T i = + (void)f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(); + } + f.get(); + BOOST_TEST(true); + } + { + typedef void T; + boost::future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + try + { + f.get(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::broken_promise)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp new file mode 100644 index 000000000..6a1a35292 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/emplace_pass.cpp @@ -0,0 +1,207 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// template <class ...Args> +// void promise::emplace(Args&& ... args); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + A(int i, int j) : + value(i+j) + { + } + BOOST_THREAD_MOVABLE_ONLY(A) + + A(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + } + A& operator=(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + return *this; + } + int value; +}; + +A make(int i) { + return A(i); +} +A make(int i, int j) { + return A(i, j); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + movable2(int i, int j) : value_(i+j){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true)); +#endif +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(); + try + { + T a = f.get(); (void)a; + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(3); + BOOST_TEST(f.get().value == 3); + try + { + T j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<movable2> p; + boost::future<movable2> f = p.get_future(); + p.emplace(3); + BOOST_TEST(f.get().value_ == 3); + try + { + p.emplace(3); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<A> p; + boost::future<A> f = p.get_future(); + p.emplace(1,2); + BOOST_TEST(f.get().value == 3); + try + { + p.emplace(1,2); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + typedef A T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.emplace(3); + boost::promise<T> p2(boost::move(p)); + BOOST_TEST(f.get().value == 3); + + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp new file mode 100644 index 000000000..13a63b13d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/get_future_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// future<R> get_future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::promise<double> p; + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + p.set_value(105.5); + BOOST_TEST(f.get() == 105.5); + } + { + boost::promise<double> p; + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::future_already_retrieved)); + } + } + { + boost::promise<double> p; + boost::promise<double> p0 = boost::move(p); + try + { + boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp new file mode 100644 index 000000000..0190527c0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/move_assign_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class promise<R> + +// promise& operator=(promise&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +boost::mutex m0; +boost::mutex m1; + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + + { + boost::promise<int&> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int&> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p0(boost::allocator_arg, test_allocator<void>()); + boost::promise<void> p(boost::allocator_arg, test_allocator<void>()); + BOOST_TEST(test_alloc_base::count == 2); + p = boost::move(p0); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + +#endif + { + boost::promise<int> p0; + boost::promise<int> p; + p = boost::move(p0); + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + { + boost::promise<int&> p0; + boost::promise<int&> p; + p = boost::move(p0); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + { + boost::promise<void> p0; + boost::promise<void> p; + p = boost::move(p0); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp new file mode 100644 index 000000000..a72eb1829 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/move_ctor_pass.cpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class promise<R> + +// promise(promise&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +boost::mutex m; + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + std::cout << __LINE__ << std::endl; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + std::cout << __LINE__ << std::endl; + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 1); + } + std::cout << __LINE__ << std::endl; + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<int&> p0(boost::allocator_arg, test_allocator<int>()); + boost::promise<int&> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); + { + boost::promise<void> p0(boost::allocator_arg, test_allocator<void>()); + boost::promise<void> p(boost::move(p0)); + BOOST_TEST(test_alloc_base::count == 1); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + BOOST_TEST(test_alloc_base::count == 1); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + boost::promise<int> p0; + boost::promise<int> p(boost::move(p0)); + std::cout << __LINE__ << std::endl; + boost::future<int> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + std::cout << __LINE__ << std::endl; + BOOST_TEST(f.valid()); + std::cout << __LINE__ << std::endl; + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + std::cout << __LINE__ << std::endl; + } + std::cout << __LINE__ << std::endl; + { + boost::promise<int&> p0; + boost::promise<int&> p(boost::move(p0)); + boost::future<int&> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + { + boost::promise<void> p0; + boost::promise<void> p(boost::move(p0)); + boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + try + { + f = BOOST_THREAD_MAKE_RV_REF(p0.get_future()); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state)); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp new file mode 100644 index 000000000..d23d0befb --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_exception_at_thread_exit(exception_ptr p); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void func(boost::promise<int> p) +#else +boost::promise<int> p; +void func() +#endif +{ + //p.set_exception(boost::make_exception_ptr(3)); + p.set_exception_at_thread_exit(boost::make_exception_ptr(3)); +} + +int main() +{ + { + typedef int T; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::promise<T> p; + boost::future<T> f = p.get_future(); + boost::thread(func, boost::move(p)).detach(); +#else + boost::future<T> f = p.get_future(); + boost::thread(func).detach(); +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + boost::promise<T> p2; + boost::future<T> f = p2.get_future(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func, boost::move(p2)).detach(); +#else + p = boost::move(p2); + boost::thread(func).detach(); +#endif + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp new file mode 100644 index 000000000..c27aec293 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_exception_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void set_exception(exception_ptr p); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +int main() +{ + + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_exception(boost::make_exception_ptr(3)); + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + try + { + p.set_exception(boost::make_exception_ptr(3)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_exception_deferred(boost::make_exception_ptr(3)); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + try + { + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> i) + { + BOOST_TEST(i.value == 3); + } + try + { + p.set_exception(boost::make_exception_ptr(3)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp new file mode 100644 index 000000000..a143dc636 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<R&>::set_value_at_thread_exit(R& r); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <memory> + +int i = 0; + +//void func(boost::promise<int&> p) +boost::promise<int&> p; +void func() +{ + p.set_value_at_thread_exit(i); + i = 4; +} + +int main() +{ + { + //boost::promise<int&> p; + boost::future<int&> f = p.get_future(); + //boost::thread(func, boost::move(p)).detach(); + boost::thread(func).detach(); + int r = f.get(); + BOOST_TEST(r == 4); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp new file mode 100644 index 000000000..6acfb62d1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_lvalue_pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<R&>::set_value(R& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +int main() +{ + + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value_deferred(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value_deferred(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int& T; + int i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + int& j = f.get(); + BOOST_TEST(j == 3); + ++i; + BOOST_TEST(j == 4); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp new file mode 100644 index 000000000..0b23b4834 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value_at_thread_exit(R&& p); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/csbl/memory/unique_ptr.hpp> + +boost::promise<boost::csbl::unique_ptr<int> > p; +boost::promise<boost::csbl::unique_ptr<int> > p2; +void func() +{ + boost::csbl::unique_ptr<int> uptr(new int(5)); + p.set_value_at_thread_exit(boost::move(uptr)); +} +void func2() +{ + p2.set_value_at_thread_exit(boost::csbl::make_unique<int>(5)); +} + +int main() +{ + { + boost::future<boost::csbl::unique_ptr<int> > f = p.get_future(); + boost::thread(func).detach(); + BOOST_TEST(*f.get() == 5); + } + { + boost::future<boost::csbl::unique_ptr<int> > f = p2.get_future(); + boost::thread(func2).detach(); + BOOST_TEST(*f.get() == 5); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp new file mode 100644 index 000000000..63260d726 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_rvalue_pass.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011,2014 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value(R&& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() : + value(0) + { + } + A(int i) : + value(i) + { + } + BOOST_THREAD_MOVABLE_ONLY(A) + + A(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + } + A& operator=(BOOST_THREAD_RV_REF(A) rhs) + { + if(rhs.value==0) + throw 9; + else + { + value=rhs.value; + rhs.value=0; + } + return *this; + } + int value; +}; + +A make(int i) { + return A(i); +} + +struct movable2 +{ + int value_; + BOOST_THREAD_MOVABLE_ONLY(movable2) + movable2() : value_(1){} + movable2(int i) : value_(i){} + + //Move constructor and assignment + movable2(BOOST_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; } + + movable2 & operator=(BOOST_THREAD_RV_REF(movable2) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return !value_; } + + int value() const //Observer + { return value_; } +}; + + +movable2 move_return_function2(int i) { + return movable2(i); +} + +int main() +{ +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT((boost::is_copy_constructible<movable2>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<movable2>::value == true)); + BOOST_STATIC_ASSERT((boost::is_copy_constructible<A>::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<A>::value == true)); +#endif + + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value(boost::move(i)); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value_deferred(boost::move(i)); + BOOST_TEST(!f.is_ready()); + p.notify_deferred(); + + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value((T())); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value_deferred((T())); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 9); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(f.get().value == 3); + try + { + T j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + movable2 i(3); + boost::promise<movable2> p; + boost::future<movable2> f = p.get_future(); + p.set_value(move_return_function2(3)); + BOOST_TEST(f.get().value_ == 3); + try + { + movable2 j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + boost::promise<A> p; + boost::future<A> f = p.get_future(); + p.set_value(make(3)); + BOOST_TEST(f.get().value == 3); + try + { + A j(3); + p.set_value(boost::move(j)); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + BOOST_TEST(f.get().value == 3); + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + boost::future<T> f2(boost::move(f)); + BOOST_TEST(f2.get().value == 3); + + } + { + typedef A T; + T i(3); + boost::promise<T> p; + p.set_value(boost::move(i)); + BOOST_TEST(i.value == 0); + boost::promise<T> p2(boost::move(p)); + boost::future<T> f = p2.get_future(); + BOOST_TEST(f.get().value == 3); + + } + + { + typedef boost::future<int> T; + boost::promise<int> pi; + T fi=pi.get_future(); + pi.set_value(3); + + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(boost::move(fi)); + boost::future<T> f2(boost::move(f)); + BOOST_TEST(f2.get().get() == 3); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp new file mode 100644 index 000000000..4972cb7d8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value_at_thread_exit(const R& r); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void func(boost::promise<int> p) +#else +boost::promise<int> p; +void func() +#endif +{ + const int i = 5; + p.set_value_at_thread_exit(i); +} + +int main() +{ + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::promise<int> p; + boost::future<int> f = p.get_future(); + boost::thread(func, boost::move(p)).detach(); +#else + boost::future<int> f = p.get_future(); + boost::thread(func).detach(); +#endif + try + { + BOOST_TEST(f.get() == 5); + } + catch (...) + { + BOOST_TEST(false); + } + } + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + boost::promise<int> p2; + boost::future<int> f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + BOOST_TEST(f.get() == 5); +#endif + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp new file mode 100644 index 000000000..c79f2a23e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<void>::set_value_at_thread_exit(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int i = 0; + +boost::promise<void> p; +void func() +{ + p.set_value_at_thread_exit(); + i = 1; +} + +//void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2) +void func2_mv(boost::promise<void> p2) +{ + p2.set_value_at_thread_exit(); + i = 2; +} + +void func2(boost::promise<void> *p2) +{ + p2->set_value_at_thread_exit(); + i = 2; +} +int main() +{ + try + { + boost::future<void> f = p.get_future(); + boost::thread(func).detach(); + f.get(); + BOOST_TEST(i == 1); + + } + catch(std::exception& ) + { + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + boost::promise<void> p2; + boost::future<void> f = p2.get_future(); + p = boost::move(p2); + boost::thread(func).detach(); + f.get(); + BOOST_TEST(i == 1); + + } + catch(std::exception& ex) + { + std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl; + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + boost::promise<void> p2; + boost::future<void> f = p2.get_future(); +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + boost::thread(func2_mv, boost::move(p2)).detach(); +#else + boost::thread(func2, &p2).detach(); +#endif + f.wait(); + f.get(); + BOOST_TEST(i == 2); + } + catch(std::exception& ex) + { + std::cout << __FILE__ << ":" << __LINE__ << " " << ex.what() << std::endl; + BOOST_TEST(false); + } + catch(...) + { + BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp new file mode 100644 index 000000000..84f2fb273 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_const_pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise::set_value(const R& r); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> +#include <boost/config.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable: 4702) // unreachable code +#endif + +struct A +{ + A() + { + } + A(const A&) + { + throw 10; + } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + A& operator= (const A&) = default; +#endif +}; + +int main() +{ + + { + typedef int T; + T i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(i); + ++i; + BOOST_TEST(f.get() == 3); + --i; + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef int T; + T i = 3; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(i); + p.notify_deferred(); + ++i; + BOOST_TEST(f.get() == 3); + --i; + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef A T; + T i; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + try + { + p.set_value(i); + BOOST_TEST(false); + } + catch (int j) + { + BOOST_TEST(j == 10); + } + catch (...) + { + BOOST_TEST(false); + } + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp new file mode 100644 index 000000000..7c11d5b66 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/set_value_void_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// void promise<void>::set_value(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +struct A +{ + A() + { + } + A(const A&) + { + throw 10; + } +}; + +int main() +{ + + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value(); + f.get(); + try + { + p.set_value(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + { + typedef void T; + boost::promise<T> p; + boost::future<T> f = p.get_future(); + p.set_value_deferred(); + p.notify_deferred(); + f.get(); + try + { + p.set_value(); + BOOST_TEST(false); + } + catch (const boost::future_error& e) + { + BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied)); + } + catch (...) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp b/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp new file mode 100644 index 000000000..3b1e96c7e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/promise/use_allocator_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class promise<R> + +// promise(allocator_arg_t, const Allocator& a); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" + +int main() +{ + + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<int>, test_allocator<int> >::value), ""); + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<int&>, test_allocator<int&> >::value), ""); + BOOST_STATIC_ASSERT_MSG((boost::csbl::uses_allocator<boost::promise<void>, test_allocator<void> >::value), ""); + + return boost::report_errors(); +} + +#else +int main() +{ + return boost::report_errors(); +} +#endif + + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp new file mode 100644 index 000000000..1b23b2d16 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/copy_assign_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// shared_future& operator=(const shared_future&); + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f; + f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + +//#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp new file mode 100644 index 000000000..fd29c0fe3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/copy_ctor_pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> +// class shared_future<R> + +// shared_future(const future&); + + +#define BOOST_THREAD_VERSION 3 +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future < T > f0; + boost::shared_future<T> f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future < T > f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0((p.get_future())); + boost::shared_future<T> f = f0; + BOOST_TEST(f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future < T > f0; + boost::shared_future<T> f = f0; + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + +//#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp new file mode 100644 index 000000000..59ecea3a3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/default_pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// shared_future(); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::shared_future<int> f; + BOOST_TEST(!f.valid()); + } + { + boost::shared_future<int&> f; + BOOST_TEST(!f.valid()); + } + { + boost::shared_future<void> f; + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp new file mode 100644 index 000000000..01fb591c0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/dtor_pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// ~shared_future(); + +#define BOOST_THREAD_VERSION 3 +#include <boost/exception/exception.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include "../test_allocator.hpp" +#endif + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef int& T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<int>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); + { + typedef void T; + boost::shared_future<T> f; + { + boost::promise<T> p(boost::allocator_arg, test_allocator<T>()); + BOOST_TEST(test_alloc_base::count == 1); + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 1); + BOOST_TEST(f.valid()); + } + BOOST_TEST(test_alloc_base::count == 0); +#endif + { + typedef int T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f; + { + boost::promise<T> p; + f = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + BOOST_TEST(f.valid()); + } + BOOST_TEST(f.valid()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp new file mode 100644 index 000000000..558fb024f --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/get_pass.cpp @@ -0,0 +1,208 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_future.hpp> + +// class shared_future<R> + +// const R& shared_future::get(); +// R& shared_future<R&>::get(); +// void shared_future<void>::get(); +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +namespace boost +{ +template <typename T> +struct wrap +{ + wrap(T const& v) : value(v){} + T value; + +}; + +template <typename T> +exception_ptr make_exception_ptr(T v) { + return copy_exception(wrap<T>(v)); +} +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(3); +} + +void func2(boost::promise<int> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3)); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + j = 5; + p.set_value(j); +} + +void func4(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(3.5)); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_value(); +} + +void func6(boost::promise<void> p) +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + p.set_exception(boost::make_exception_ptr(4)); +} + + +int main() +{ + { + typedef int T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + p.set_value(3); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func2, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 3); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + } + { + typedef int& T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + int j=5; + p.set_value(j); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 5); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func4, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(3.5)); +#endif + try + { + BOOST_TEST(f.valid()); + BOOST_TEST(f.get() == 3); + BOOST_TEST(false); + } + catch (boost::wrap<double> const& i) + { + BOOST_TEST(i.value == 3.5); + } + BOOST_TEST(f.valid()); + } + } + + typedef void T; + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + p.set_value(); +#endif + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(f.valid()); + } + { + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func6, boost::move(p)).detach(); +#else + p.set_exception(boost::make_exception_ptr(4)); +#endif + try + { + BOOST_TEST(f.valid()); + f.get(); + BOOST_TEST(false); + } + catch (boost::wrap<int> const& i) + { + BOOST_TEST(i.value == 4); + } + catch (...) + { + BOOST_TEST(false); + } + BOOST_TEST(f.valid()); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp new file mode 100644 index 000000000..40ff4992c --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/move_assign_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class shared_future<R> + +// shared_future& shared_future=(shared_future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f; + f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp new file mode 100644 index 000000000..533f5ec90 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/move_ctor_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <future> + +// class shared_future<R> + +// shared_future(shared_future&& rhs); + +#define BOOST_THREAD_VERSION 3 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef int& T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f0 = BOOST_THREAD_MAKE_RV_REF(p.get_future()); + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(f.valid()); + } + { + typedef void T; + boost::shared_future<T> f0; + boost::shared_future<T> f = boost::move(f0); + BOOST_TEST(!f0.valid()); + BOOST_TEST(!f.valid()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp new file mode 100644 index 000000000..73b42fc8a --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/then_executor_pass.cpp @@ -0,0 +1,149 @@ +// 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executor.hpp> +#include <boost/detail/lightweight_test.hpp> + +#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; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG; + return ; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(ex, &p2); + BOOST_TEST(f2.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(ex, &p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).share().then(ex, &p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(ex, &p2).share(); + boost::future<int> f2= f21.then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(ex, &p2).share(); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::future<int> f2= f1.then(ex, &p2).share().then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::basic_thread_pool ex(1); + boost::future<int> f2 = boost::async(p1).share().then(ex, &p2).share().then(ex, &p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp new file mode 100644 index 000000000..e7cca062e --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/then_pass.cpp @@ -0,0 +1,156 @@ +// 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) + +// <boost/thread/future.hpp> + +// class future<R> + +// template<typename F> +// auto then(F&& func) -> future<decltype(func(*this))>; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#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; + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG; + return 1; +} + +int p2(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG; + return 2 * i; +} + +void p3(boost::shared_future<int> f) +{ + BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG; + BOOST_TEST(f.valid()); + int i = f.get(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); + BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG; + return ; +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + BOOST_TEST(f2.valid()); + try + { + BOOST_TEST(f2.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = f1.then(&p2); + boost::future<int> f3 = f1.then(&p2); + BOOST_TEST(f2.valid()); + BOOST_TEST(f3.valid()); + try + { + BOOST_TEST(f2.get()==2); + BOOST_TEST(f3.get()==2); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<void> f2 = f1.then(&p3); + BOOST_TEST(f2.valid()); + try + { + f2.wait(); + } + catch (std::exception& ex) + { + BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + catch (...) + { + BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG; + BOOST_TEST(false); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).share().then(&p2); + BOOST_TEST(f2.get()==2); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::shared_future<int> f21 = f1.then(&p2).share(); + boost::future<int> f2= f21.then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::shared_future<int> f1 = boost::async(p1).share(); + boost::future<int> f2= f1.then(&p2).share().then(&p2); + BOOST_TEST(f2.get()==4); + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + boost::future<int> f2 = boost::async(p1).share().then(&p2).share().then(&p2); + BOOST_TEST(f2.get()==4); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp new file mode 100644 index 000000000..e9d8ac684 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// future_status +// wait_for(const chrono::duration<Rep, Period>& rel_time) const; + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_for(ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_for(ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp new file mode 100644 index 000000000..d2d1b31f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// void wait() const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#else + func3(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#else + func5(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + f.wait(); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + BOOST_TEST(t1 - t0 < ms(50)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp b/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp new file mode 100644 index 000000000..8b05725e7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/future.hpp> + +// class shared_future<R> + +// template <class Rep, class Period> +// future_status +// wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; + +//#define BOOST_THREAD_VERSION 3 +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_USES_LOG +#define BOOST_THREAD_USES_LOG_THREAD_ID +#include <boost/thread/detail/log.hpp> + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +namespace boost +{ + template <typename OStream> + OStream& operator<<(OStream& os , boost::future_status st ) + { + os << underlying_cast<int>(st) << " "; + return os; + } + template <typename T> + struct wrap + { + wrap(T const& v) : + value(v) + { + } + T value; + + }; + + template <typename T> + exception_ptr make_exception_ptr(T v) + { + return copy_exception(wrap<T> (v)); + } +} + +void func1(boost::promise<int> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(3); +} + +int j = 0; + +void func3(boost::promise<int&> p) +{ + boost::this_thread::sleep_for(ms(500)); + j = 5; + p.set_value(j); +} + +void func5(boost::promise<void> p) +{ + boost::this_thread::sleep_for(ms(500)); + p.set_value(); +} + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +int main() +{ + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + { + typedef boost::chrono::high_resolution_clock Clock; + { + typedef int T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func1, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func1(boost::move(p)); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef int& T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func3, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func3(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + typedef void T; + boost::promise<T> p; + boost::shared_future<T> f((p.get_future())); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + boost::thread(func5, boost::move(p)).detach(); +#endif + BOOST_TEST(f.valid()); + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(250)) , boost::future_status::timeout); + BOOST_TEST(f.valid()); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#else + func5(boost::move(p)); +#endif + BOOST_TEST_EQ(f.wait_until(Clock::now() + ms(750)) , boost::future_status::ready); + BOOST_TEST(f.valid()); + Clock::time_point t0 = Clock::now(); + f.wait(); + Clock::time_point t1 = Clock::now(); + BOOST_TEST(f.valid()); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + } + BOOST_THREAD_LOG << BOOST_THREAD_END_LOG; + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/futures/test_allocator.hpp b/src/boost/libs/thread/test/sync/futures/test_allocator.hpp new file mode 100644 index 000000000..a73d7d8e3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/test_allocator.hpp @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +#ifndef BOOST_THREAD_TEST_ALLOCATOR_HPP +#define BOOST_THREAD_TEST_ALLOCATOR_HPP + +#include <cstddef> +#include <boost/type_traits.hpp> +#include <boost/thread/detail/move.hpp> +#include <cstdlib> +#include <new> +#include <climits> + +class test_alloc_base +{ +public: + static int count; +public: + static int throw_after; +}; + +int test_alloc_base::count = 0; +int test_alloc_base::throw_after = INT_MAX; + +template <class T> +class test_allocator + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef typename boost::add_lvalue_reference<value_type>::type reference; + typedef typename boost::add_lvalue_reference<const value_type>::type const_reference; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + pointer allocate(size_type n, const void* = 0) + { + if (count >= throw_after) + throw std::bad_alloc(); + ++count; + return (pointer)std::malloc(n * sizeof(T)); + } + void deallocate(pointer p, size_type) + {--count; std::free(p);} + size_type max_size() const throw() + {return UINT_MAX / sizeof(T);} + void construct(pointer p, const T& val) + {::new(p) T(val);} + + void construct(pointer p, BOOST_THREAD_RV_REF(T) val) + {::new(p) T(boost::move(val));} + + void destroy(pointer p) {p->~T();} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <> +class test_allocator<void> + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef void value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <class T> +class other_allocator +{ + int data_; + + template <class U> friend class other_allocator; + +public: + typedef T value_type; + + other_allocator() : data_(-1) {} + explicit other_allocator(int i) : data_(i) {} + template <class U> other_allocator(const other_allocator<U>& a) + : data_(a.data_) {} + T* allocate(std::size_t n) + {return (T*)std::malloc(n * sizeof(T));} + void deallocate(T* p, std::size_t) + {std::free(p);} + + other_allocator select_on_container_copy_construction() const + {return other_allocator(-2);} + + friend bool operator==(const other_allocator& x, const other_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const other_allocator& x, const other_allocator& y) + {return !(x == y);} + + typedef boost::true_type propagate_on_container_copy_assignment; + typedef boost::true_type propagate_on_container_move_assignment; + typedef boost::true_type propagate_on_container_swap; + +#ifdef BOOST_NO_SFINAE_EXPR + std::size_t max_size() const + {return UINT_MAX / sizeof(T);} +#endif // BOOST_NO_SFINAE_EXPR + +}; + +#endif // BOOST_THREAD_TEST_ALLOCATOR_HPP diff --git a/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp new file mode 100644 index 000000000..2646074f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/iterators_pass.cpp @@ -0,0 +1,362 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// template< typename InputIterator> +// future<vector<typename InputIterator::value_type> > +// when_all(InputIterator first, InputIterator last) + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::csbl::vector<boost::future<int> > v; + boost::future<int> f1; + v.push_back(boost::move(f1)); + v.push_back(boost::make_ready_future(321)); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(v[1].valid()); + + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res.size() == 2); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + // has exception + //BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + try { + res[0].get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + BOOST_TEST(! all.is_ready()); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f) + { + boost::csbl::vector<boost::future<int> > v = f.get(); + return v[0].get() + v[1].get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp new file mode 100644 index 000000000..613e2368d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/none_pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// future<tuple<>> when_all(); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + { + boost::future<boost::csbl::tuple<> > all = boost::when_all(); + BOOST_TEST(all.valid()); + BOOST_TEST(all.is_ready()); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp new file mode 100644 index 000000000..026abcf53 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/one_pass.cpp @@ -0,0 +1,186 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T>> when_all(T&&); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + BOOST_TEST(! f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_all(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_all(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#endif +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp new file mode 100644 index 000000000..f3b93b8be --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_all/variadic_pass.cpp @@ -0,0 +1,300 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T, Ts...>> when_all(T&&, Ts&& ...); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(! f1.valid()); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + BOOST_TEST(! all.is_ready()); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f) + { + boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get(); + return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp new file mode 100644 index 000000000..03336d022 --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/iterators_pass.cpp @@ -0,0 +1,363 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// template< typename InputIterator> +// future<vector<typename InputIterator::value_type> > +// when_any(InputIterator first, InputIterator last) + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::csbl::vector<boost::future<int> > v; + boost::future<int> f1; + v.push_back(boost::move(f1)); + v.push_back(boost::make_ready_future(321)); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(v[1].valid()); + + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res.size() == 2); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + // has exception + //BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[0].is_ready()); + BOOST_TEST(v[1].valid()); + BOOST_TEST(v[1].is_ready()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + try { + res[0].get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + if (0) // fixme + BOOST_TEST(! res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::csbl::vector<boost::shared_future<int> > v; + v.push_back(f1); + v.push_back(f2); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end()); + if (0) // fixme + BOOST_TEST(v[0].valid()); + if (0) // fixme + BOOST_TEST(v[1].valid()); + BOOST_TEST(all.valid()); + boost::csbl::vector<boost::shared_future<int> > res = all.get(); + BOOST_TEST(res[0].valid()); + BOOST_TEST(res[0].is_ready()); + BOOST_TEST(res[0].get() == 123); + BOOST_TEST(res[1].valid()); + BOOST_TEST(! res[1].is_ready()); + BOOST_TEST(res[1].get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::csbl::vector<boost::future<int> > v; + v.push_back(boost::move(f1)); + v.push_back(boost::move(f2)); + BOOST_TEST(v[0].valid()); + BOOST_TEST(v[1].valid()); + boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end()); + BOOST_TEST(! v[0].valid()); + BOOST_TEST(! v[1].valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f) + { + boost::csbl::vector<boost::future<int> > v = f.get(); + return v[0].get() + v[1].get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp new file mode 100644 index 000000000..2edd0bc6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/none_pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// future<tuple<>> when_any(); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + { + boost::future<boost::csbl::tuple<> > all = boost::when_any(); + BOOST_TEST(all.valid()); + BOOST_TEST(all.is_ready()); + } +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp new file mode 100644 index 000000000..61882ef6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/one_pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// future<tuple<T>> when_any(T&&); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + BOOST_TEST(! f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + pt1(); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<boost::csbl::tuple<boost::future<int> > > all = boost::when_any(boost::move(f1)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int> > > all = boost::when_any(f1); + BOOST_TEST(f1.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + } +#endif +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp b/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp new file mode 100644 index 000000000..09b3951fc --- /dev/null +++ b/src/boost/libs/thread/test/sync/futures/when_any/variadic_pass.cpp @@ -0,0 +1,323 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2014 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) + +// <boost/thread/future.hpp> + +// template <class T, class Ts> +// future<tuple<T, Ts...>> when_any(T&&, Ts&& ...); + +#include <boost/config.hpp> + +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <stdexcept> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +int p1() +{ + return 123; +} + +int thr() +{ + throw std::logic_error("123"); +} +int p2() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + return 321; +} + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + if (0) // todo not yet implemented + { // invalid future copy-constructible + boost::future<int> f1; + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(! f1.valid()); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + // has exception + //BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready future copy-constructible + boost::future<int> f1 = boost::make_ready_future(123); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // is_ready shared_future copy-constructible + boost::shared_future<int> f1 = boost::make_ready_future(123).share(); + boost::shared_future<int> f2 = boost::make_ready_future(321).share(); + BOOST_TEST(f1.valid()); + BOOST_TEST(f1.is_ready()); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + if (0) // todo FAILS not yet implemented + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task future copy-constructible + boost::packaged_task<int()> pt1(&thr); + boost::future<int> f1 = pt1.get_future(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::future<int> f2 = pt2.get_future(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + pt1(); + pt2(); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + try { + boost::csbl::get<0>(res).get(); + BOOST_TEST(false); + } catch (std::logic_error& ex) { + BOOST_TEST(ex.what() == std::string("123")); + } catch (...) { + BOOST_TEST(false); + } + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // packaged_task shared_future copy-constructible + boost::packaged_task<int()> pt1(&p1); + boost::shared_future<int> f1 = pt1.get_future().share(); + BOOST_TEST(f1.valid()); + boost::packaged_task<int()> pt2(&p2); + boost::shared_future<int> f2 = pt2.get_future().share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + BOOST_TEST(! all.is_ready()); + pt1(); + pt2(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(300)); + BOOST_TEST(all.is_ready()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share(); + BOOST_TEST(f1.valid()); + boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share(); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + { // async future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::make_ready_future(321); + BOOST_TEST(f2.valid()); + BOOST_TEST(f2.is_ready()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + //BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + std::cout << __FILE__ << " " << __LINE__ << std::endl; + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::deferred, &p1); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + //BOOST_TEST(! boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred future copy-constructible + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + boost::future<int> f2 = boost::async(boost::launch::deferred, &p2); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + //BOOST_TEST(boost::csbl::get<0>(res).is_ready()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } + // fixme darwin-4.8.0_11 terminate called without an active exception + { // deferred shared_future copy-constructible + boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share(); + boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share(); + boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_any(f1, f2); + BOOST_TEST(f1.valid()); + BOOST_TEST(f2.valid()); + BOOST_TEST(all.valid()); + boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get(); + BOOST_TEST(boost::csbl::get<0>(res).valid()); + BOOST_TEST(boost::csbl::get<1>(res).valid()); + BOOST_TEST(boost::csbl::get<0>(res).is_ready() || boost::csbl::get<1>(res).is_ready()); + BOOST_TEST(boost::csbl::get<0>(res).get() == 123); + BOOST_TEST(boost::csbl::get<1>(res).get() == 321); + } +#endif +#if ! defined BOOST_NO_CXX11_LAMBDAS + { // async futures copy-constructible then() + boost::future<int> f1 = boost::async(boost::launch::async, &p1); + BOOST_TEST(f1.valid()); + boost::future<int> f2 = boost::async(boost::launch::async, &p2); + BOOST_TEST(f2.valid()); + boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_any(boost::move(f1), boost::move(f2)); + BOOST_TEST(! f1.valid()); + BOOST_TEST(! f2.valid()); + BOOST_TEST(all.valid()); + boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f) + { + boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get(); + return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get(); + }); + BOOST_TEST(sum.valid()); + BOOST_TEST(sum.get() == 444); + } +#endif +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp new file mode 100644 index 000000000..bd9ff152f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/deque_views/single_thread_pass.cpp @@ -0,0 +1,468 @@ +// Copyright (C) 2014 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) + +// <boost/thread/sync_deque.hpp> + +// class sync_deque<T> + +// sync_deque(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/concurrent_queues/sync_deque.hpp> +#include <boost/thread/concurrent_queues/deque_adaptor.hpp> +#include <boost/thread/concurrent_queues/deque_views.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class non_copyable +{ + int val; +public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES +BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value ); +BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value ); +#endif + +int main() +{ + + { + // default queue invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // default queue invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + + { + // empty queue try_pull fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue push rvalue/non_copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue push rvalue/non_copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > q; + //boost::sync_deque<non_copyable> q; + //boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#if 0 + { + // empty queue try_push rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + int i=0; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue try_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue try_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue nonblocking_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue nonblocking_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<non_copyable> > sq; + boost::deque_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // closed invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed invariants + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_back<int> q(sq); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + sq.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front fails + boost::deque_adaptor<boost::sync_deque<int> > sq; + boost::deque_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp new file mode 100644 index 000000000..b6039c556 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/adopt_lock_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock(); + boost::lock_guard<boost::mutex> lg(m, boost::adopt_lock); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock(); + boost::lock_guard<boost::mutex> lg(m, boost::adopt_lock); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp new file mode 100644 index 000000000..a3957c750 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_assign_fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard& operator=(lock_guard const&) = delete; + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::lock_guard<boost::mutex> lk0(m0); + boost::lock_guard<boost::mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp new file mode 100644 index 000000000..5c1b3a1c2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/copy_ctor_fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(lock_guard const&) = delete; + + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::lock_guard<boost::mutex> lk0(m0); + boost::lock_guard<boost::mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp new file mode 100644 index 000000000..4fcc26a9b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/default_pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex &); + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::lock_guard<boost::mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::lock_guard<boost::mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp new file mode 100644 index 000000000..9aab78ddd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_fail.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Tom Hughes +// +// 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_, adopt_lock_t) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void fail() +{ + boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp new file mode 100644 index 000000000..a158677ad --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_adopt_lock_compile_pass.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Tom Hughes +// +// 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_, adopt_lock_t) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void pass() +{ + m.lock(); + boost::lock_guard<boost::mutex> lk(m, boost::adopt_lock); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp new file mode 100644 index 000000000..eead4501c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_fail.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Tom Hughes +// +// 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void fail() +{ + boost::lock_guard<boost::mutex> lk0(m); + boost::lock_guard<boost::mutex> lk1(m); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp new file mode 100644 index 000000000..aee2e40e4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/lock_guard_compile_pass.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2018 Tom Hughes +// +// 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Mutex> class lock_guard; + +// lock_guard(Mutex& m_) + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +void pass() +{ + { + boost::lock_guard<boost::mutex> lk0(m); + } + boost::lock_guard<boost::mutex> lk1(m); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp new file mode 100644 index 000000000..cecdc84ce --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_adopt_lock_pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Lockable> +// lock_guard<Lockable> make_lock_guard(Lockable &, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock(); + auto&& lg = boost::make_lock_guard(m, boost::adopt_lock); (void)lg; + + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock(); + auto&& lg = boost::make_lock_guard(m, boost::adopt_lock); (void)lg; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} +#endif + +int main() +{ +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp new file mode 100644 index 000000000..853fae743 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/make_lock_guard_pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/lock_guard.hpp> + +// template <class Lockable> +// lock_guard<Lockable> make_lock_guard(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + { + const auto&& lg = boost::make_lock_guard(m); (void)lg; + t1 = Clock::now(); + } +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp new file mode 100644 index 000000000..7c2d39375 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/lock_guard/types_pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class lock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::lock_guard<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..c5d9a39b5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock& operator=(nested_strict_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk0(lk0); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk1(lk1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..1c0abf94a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock(nested_strict_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > lk0(m0); + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp new file mode 100644 index 000000000..0182bdd95 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp @@ -0,0 +1,79 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// nested_strict_lock(Mutex &); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + boost::unique_lock<boost::mutex> lg(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlg(lg); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + boost::unique_lock<boost::mutex> lg(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlg(lg); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + { + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp new file mode 100644 index 000000000..5a10728cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/make_nested_strict_lock_pass.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2011 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) + +// <boost/thread/strict_lock.hpp> + +// template <class Lockable> +// strict_lock<Lockable> make_strict_lock(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + boost::unique_lock<boost::mutex> lg(m); + { + const auto&& nlg = boost::make_nested_strict_lock(lg); (void)nlg; + t1 = Clock::now(); + } +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp new file mode 100644 index 000000000..be06b6a06 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp @@ -0,0 +1,60 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class nested_strict_lock; + +// bool owns_lock(Mutex *) const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + boost::mutex m2; + { + boost::unique_lock<boost::mutex> lk(m); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + m.lock(); + boost::unique_lock<boost::mutex> lk(m, boost::adopt_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + { + boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk); + BOOST_TEST(nlk.owns_lock(&m) == true); + BOOST_TEST(!nlk.owns_lock(&m2) == true); + } + BOOST_TEST(lk.owns_lock() == true && lk.mutex()==&m); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp new file mode 100644 index 000000000..5a7c690e4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp @@ -0,0 +1,35 @@ +// 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Lock> +// class nested_strict_lock +// { +// public: +// typedef typename Lock::mutex_type mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::nested_strict_lock<boost::unique_lock<boost::mutex> >::mutex_type, + boost::mutex>::value), ""); + + BOOST_STATIC_ASSERT_MSG((boost::is_strict_lock<boost::nested_strict_lock<boost::unique_lock<boost::mutex> > >::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..408e0f267 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_assign_fail.cpp @@ -0,0 +1,33 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class reverse_lock; + +// reverse_lock& operator=(reverse_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> + + +int main() +{ + boost::mutex m0; + boost::mutex m1; + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg0(lk0); + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg1(lk1); + lg1 = lg0; + } + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..c936c11b8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/copy_ctor_fail.cpp @@ -0,0 +1,32 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class reverse_lock; + +// reverse_lock(reverse_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::mutex m0; + boost::unique_lock<boost::mutex> lk0(m0); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg0(lk0); + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg1(lg0); + } +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp new file mode 100644 index 000000000..13a17fd3a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp @@ -0,0 +1,34 @@ +// 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class unlock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/mutex.hpp> +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::reverse_lock<boost::unique_lock<boost::mutex> >::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp new file mode 100644 index 000000000..57a1f1e01 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/reverse_lock/unique_lock_ctor_pass.cpp @@ -0,0 +1,52 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unlock_guard; + +// unlock_guard(unlock_guard const&) = delete; + +#include <boost/thread/reverse_lock.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + { + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m); + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg(lk); + BOOST_TEST(!lk.owns_lock()); + BOOST_TEST(lk.mutex()==0); + } + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + } + + { + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + BOOST_TEST(! lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + { + boost::reverse_lock<boost::unique_lock<boost::mutex> > lg(lk); + BOOST_TEST(!lk.owns_lock()); + BOOST_TEST(lk.mutex()==0); + } + BOOST_TEST(lk.owns_lock()); + BOOST_TEST(lk.mutex()==&m); + } + + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..f9089e7a8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, adopt_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::shared_mutex m; + m.lock_shared(); + boost::shared_lock<boost::shared_mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..2bc99f34b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..43fddebe8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp new file mode 100644 index 000000000..9ccae93b7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_lock<boost::shared_mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..84388aca4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m; + m.lock(); + boost::shared_lock<boost::shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..45037c224 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..ef54e229f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_mutex.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(shared_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::unique_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::shared_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::shared_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(boost::upgrade_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..307c76142 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::shared_lock<boost::shared_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp new file mode 100644 index 000000000..38f6e7d7d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + + { + boost::unique_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (boost::unique_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp new file mode 100644 index 000000000..36ecb6a5a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock& operator=(shared_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + + { + boost::upgrade_lock<boost::shared_mutex> lk0(m); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk( (boost::upgrade_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::shared_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..f50aa6199 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// explicit shared_lock(Mutex& m); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock<boost::shared_mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::shared_lock<boost::shared_mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..41d9cd8f9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Clock, class Duration> +// shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::shared_lock<boost::shared_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..5f3036c0c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// shared_lock(mutex_type& m, try_to_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } +#else +// time_point t0 = Clock::now(); +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::shared_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..456c26dfd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/lock_pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::shared_lock < boost::shared_mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::shared_lock < boost::shared_mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..07d32df39 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct shared_mutex +{ + template <class Rep, class Period> + bool try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..6a1997238 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct shared_mutex +{ + bool try_lock_shared() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..cdfd0e161 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_until_called = false; + +struct shared_mutex +{ + template <class Clock, class Duration> + bool try_lock_shared_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::shared_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..e8ed7c74c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool unlock_called = false; + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + unlock_called = true; + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..11f366bd6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void swap(shared_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk1(m); + boost::shared_lock<shared_mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..c0ccb8b9d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_shared() + { + } + void unlock_shared() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk1(m); + boost::shared_lock<shared_mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp new file mode 100644 index 000000000..c39ca50aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + static int lock_count; + static int unlock_count; + void lock_shared() + { + ++lock_count; + } + void unlock_shared() + { + ++unlock_count; + } +}; + +int shared_mutex::lock_count = 0; +int shared_mutex::unlock_count = 0; + +shared_mutex m; + +int main() +{ + boost::shared_lock<shared_mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..2012186ae --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::shared_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..407bfcc6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/op_bool_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock < boost::shared_mutex > lk0; + BOOST_TEST(bool(lk0) == false); + boost::shared_lock < boost::shared_mutex > lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..dce14d3e9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class shared_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::shared_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::shared_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp new file mode 100644 index 000000000..2f83ef98f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class shared_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::shared_lock<boost::shared_mutex>::mutex_type, + boost::shared_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp new file mode 100644 index 000000000..fe125e8a0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/adopt_lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(mutex_type& m, adopt_lock_t); + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +boost::shared_mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + m.lock_shared(); + boost::shared_lock_guard<boost::shared_mutex> lg(m, boost::adopt_lock); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + m.lock_shared(); + boost::shared_lock_guard<boost::shared_mutex> lg(m, boost::adopt_lock); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp new file mode 100644 index 000000000..43607ac26 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_assign_fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard& operator=(shared_lock_guard const&) = delete; + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock_guard<boost::shared_mutex> lk0(m0); + boost::shared_lock_guard<boost::shared_mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp new file mode 100644 index 000000000..a7d4f006d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/copy_ctor_fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(shared_lock_guard const&) = delete; + + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::shared_lock_guard<boost::shared_mutex> lk0(m0); + boost::shared_lock_guard<boost::shared_mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp new file mode 100644 index 000000000..694ba4a14 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/default_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_lock_guard.hpp> + +// template <class Mutex> class shared_lock_guard; + +// shared_lock_guard(shared_lock_guard const&) = delete; + +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +boost::shared_mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::shared_lock_guard<boost::shared_mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::shared_lock_guard<boost::shared_mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp new file mode 100644 index 000000000..57a2116d1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/shared_lock_guard/types_pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_lock_guard.hpp> + +// <mutex> + +// template <class Mutex> +// class shared_lock_guard +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/shared_lock_guard.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::shared_lock_guard<boost::shared_mutex>::mutex_type, + boost::shared_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp new file mode 100644 index 000000000..1852224bb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_assign_fail.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock& operator=(strict_lock const&) = delete; + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::strict_lock<boost::mutex> lk0(m0); + boost::strict_lock<boost::mutex> lk1(m1); + lk1 = lk0; + +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp new file mode 100644 index 000000000..331610cb1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/copy_ctor_fail.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock(strict_lock const&) = delete; + + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::strict_lock<boost::mutex> lk0(m0); + boost::strict_lock<boost::mutex> lk1 = lk0; +} + +#include "../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp new file mode 100644 index 000000000..aa2fb0071 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/default_pass.cpp @@ -0,0 +1,74 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// strict_lock(Mutex &); + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#ifdef BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::strict_lock<boost::mutex> lg(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::strict_lock<boost::mutex> lg(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#ifdef BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp new file mode 100644 index 000000000..c5a3069f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/make_strict_lock_pass.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2011 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) + +// <boost/thread/strict_lock.hpp> + +// template <class Lockable> +// strict_lock<Lockable> make_strict_lock(Lockable &); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../../timming.hpp" + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +boost::mutex m; + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ + t0 = Clock::now(); + { + const auto&& lg = boost::make_strict_lock(m); (void)lg; + t1 = Clock::now(); + } + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} +#endif + +int main() +{ + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK && defined BOOST_THREAD_USES_CHRONO + { + m.lock(); + boost::thread t(f); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp new file mode 100644 index 000000000..c0c2ec861 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/owns_lock_pass.cpp @@ -0,0 +1,34 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class strict_lock; + +// bool owns_lock(Mutex *) const; + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#endif + +int main() +{ + boost::mutex m; + boost::mutex m2; + + boost::strict_lock<boost::mutex> lk(m); + BOOST_TEST(lk.owns_lock(&m) == true); + BOOST_TEST(!lk.owns_lock(&m2) == true); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp new file mode 100644 index 000000000..f813e5ca8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/strict_lock/types_pass.cpp @@ -0,0 +1,34 @@ +// 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class strict_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/strict_lock.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::strict_lock<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + BOOST_STATIC_ASSERT_MSG((boost::is_strict_lock<boost::strict_lock<boost::mutex> >::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..42d33378e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::mutex m; + m.lock(); + boost::unique_lock<boost::mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..d69a1eec7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock& operator=(unique_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..08fc3c344 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp new file mode 100644 index 000000000..7989b8173 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::unique_lock<boost::mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..5045af26e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + boost::unique_lock<boost::mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..19aa0575f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp new file mode 100644 index 000000000..2f385ec87 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_adopt_lock_pass.cpp @@ -0,0 +1,31 @@ +// 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) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; + m.lock(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp new file mode 100644 index 000000000..e32fad168 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_defer_lock_pass.cpp @@ -0,0 +1,32 @@ +// 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) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, defer_lock_t); + +// unique_lock(mutex_type& m, adopt_lock_t); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m; +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp new file mode 100644 index 000000000..97b625564 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_mutex_pass.cpp @@ -0,0 +1,100 @@ +// 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) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> +// unique_lock<Mutex> make_unique_lock(Mutex&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +//#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + //&& + _ = boost::make_unique_lock(m); (void)_; + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + //&& + _ = boost::make_unique_lock(m); (void)_; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} +//#else +//int main() +//{ +// return boost::report_errors(); +//} +//#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp new file mode 100644 index 000000000..d0149d906 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_lock_try_to_lock_pass.cpp @@ -0,0 +1,146 @@ +// 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; +// unique_lock<Mutex> make_unique_lock(Mutex&, try_to_lock_t); + +#define BOOST_THREAD_VERSION 4 + + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + } + { + t0 = Clock::now(); + for (;;) + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + } +#else +// time_point t0 = Clock::now(); +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + auto +#else + boost::unique_lock<boost::mutex> +#endif + lk = boost::make_unique_lock(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp new file mode 100644 index 000000000..72c574b20 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/make_unique_locks_mutex_pass.cpp @@ -0,0 +1,94 @@ +// 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) + +// <boost/thread/lock_factories.hpp> + +// template <class Mutex> +// unique_lock<Mutex> make_unique_lock(Mutex&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/lock_factories.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && ! defined BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +boost::mutex m1; +boost::mutex m2; +boost::mutex m3; + + +#if defined BOOST_THREAD_USES_CHRONO + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + auto&& _ = boost::make_unique_locks(m1,m2,m3); (void)_; + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + auto&& _ = boost::make_unique_locks(m1,m2,m3); (void)_; + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m1.lock(); + m2.lock(); + m3.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m1.unlock(); + m2.unlock(); + m3.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} +#else +int main() +{ + return boost::report_errors(); +} +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..7c84d1520 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m0; +boost::mutex m1; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0(m0); + boost::unique_lock<boost::mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + + { + + boost::unique_lock<boost::mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..cf682fbd4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(unique_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0(m); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::unique_lock<boost::mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp new file mode 100644 index 000000000..0e61cb1a7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> + lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp new file mode 100644 index 000000000..3068866f0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(shared_lock&& u, try_to_lock); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp new file mode 100644 index 000000000..f1e54cf45 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::shared_mutex> + lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp new file mode 100644 index 000000000..7437ee0e7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> + lk(boost::upgrade_lock<boost::upgrade_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp new file mode 100644 index 000000000..c72067ae9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(upgrade_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::upgrade_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp new file mode 100644 index 000000000..fdbdf2165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(upgrade_lock&& u, try_to_lock); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> lk(boost::upgrade_lock<boost::upgrade_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp new file mode 100644 index 000000000..cd33f709c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::upgrade_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::unique_lock<boost::upgrade_mutex> + lk( boost::upgrade_lock<boost::upgrade_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::upgrade_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::unique_lock<boost::upgrade_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..d5b7ca295 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit unique_lock(Mutex& m); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::unique_lock<boost::mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::unique_lock<boost::mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..53358de6e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::unique_lock<boost::timed_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_TEST(d < max_diff); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..0f0c8ded4 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// unique_lock(mutex_type& m, try_to_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + //m.unlock(); +#else +// time_point t0 = Clock::now(); +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::unique_lock<boost::mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + std::cout << "d_ns: " << d_ns.count() << std::endl; + std::cout << "d_ms: " << d_ms.count() << std::endl; + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..94edb4342 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/lock_pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::unique_lock < boost::mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::unique_lock < boost::mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..2be8416eb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct mutex +{ + template <class Rep, class Period> + bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..8553c1c0b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct mutex +{ + bool try_lock() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..df6e7369e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + + +bool try_lock_until_called = false; + +struct mutex +{ + template <class Clock, class Duration> + bool try_lock_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::unique_lock<mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..4ad954f24 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// bool unlock(); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +bool unlock_called = false; + +struct mutex +{ + void lock() + { + } + void unlock() + { + unlock_called = true; + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..617682fe3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void swap(unique_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + void lock() + { + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk1(m); + boost::unique_lock<mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..74ba5ff3f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + void lock() + { + } + void unlock() + { + } +}; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk1(m); + boost::unique_lock<mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp new file mode 100644 index 000000000..63c3831e5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct mutex +{ + static int lock_count; + static int unlock_count; + void lock() + { + ++lock_count; + } + void unlock() + { + ++unlock_count; + } +}; + +int mutex::lock_count = 0; +int mutex::unlock_count = 0; + +mutex m; + +int main() +{ + boost::unique_lock<mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(mutex::lock_count == 1); + BOOST_TEST(mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(mutex::lock_count == 1); + BOOST_TEST(mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..68f1bbb6d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..3fa18225a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_bool_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(bool(lk0) == false); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + } + + { + boost::unique_lock<boost::mutex> lk0; + if (lk0) BOOST_TEST(false); + boost::unique_lock<boost::mutex> lk1(m); + if (!lk1) BOOST_TEST(false); + lk1.unlock(); + if (lk1) BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp new file mode 100644 index 000000000..92fe0ffcb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/op_int_fail.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::mutex m; + +int main() +{ + { + boost::unique_lock<boost::mutex> lk0; + int i = int(lk0); + BOOST_TEST(i == 0); + } + + return boost::report_errors(); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..6a9f019aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class unique_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::mutex m; + + boost::unique_lock<boost::mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::unique_lock<boost::mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp new file mode 100644 index 000000000..69b963a6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/unique_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class unique_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::unique_lock<boost::mutex>::mutex_type, + boost::mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp new file mode 100644 index 000000000..1822fe0b6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/adopt_lock_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, adopt_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ + boost::shared_mutex m; + m.lock_upgrade(); + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::adopt_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp new file mode 100644 index 000000000..521304d81 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_assign_fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(upgrade_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = lk0; + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp new file mode 100644 index 000000000..8e20196b1 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/copy_ctor_fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(lk0); + BOOST_TEST(lk1.mutex() == &m1); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); +} + +#include "../../../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp new file mode 100644 index 000000000..59ea2a9a2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/default_pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> ul; + BOOST_TEST(!ul.owns_lock()); + BOOST_TEST(ul.mutex() == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp new file mode 100644 index 000000000..ececb845c --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/defer_lock_pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, adopt_lock_t); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m; + m.lock(); + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp new file mode 100644 index 000000000..b6506b9b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// upgrade_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/chrono/chrono_io.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp new file mode 100644 index 000000000..42ef355c9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/shared_mutex.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(upgrade_lock const&) = delete; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m0; +boost::shared_mutex m1; + +int main() +{ + { + boost::upgrade_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = boost::move(lk0); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::upgrade_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(m0)); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + { + boost::unique_lock<boost::shared_mutex> lk0(m0); + boost::upgrade_lock<boost::shared_mutex> lk1(m1); + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(boost::move(lk0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + + boost::upgrade_lock<boost::shared_mutex> lk1; + lk1 = BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(boost::unique_lock<boost::shared_mutex>(m0))); + BOOST_TEST(lk1.mutex() == &m0); + BOOST_TEST(lk1.owns_lock() == true); + } + return boost::report_errors(); + +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp new file mode 100644 index 000000000..5d5c0a948 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(upgrade_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::upgrade_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk( (BOOST_THREAD_MAKE_RV_REF(boost::upgrade_lock<boost::shared_mutex>(m)))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp new file mode 100644 index 000000000..ccad7b1ac --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(shared_lock<mutex_type>&&, +// const chrono::duration<Rep, Period>&); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> + lk(boost::shared_lock<boost::shared_mutex>(m), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp new file mode 100644 index 000000000..93deda8c3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(shared_lock&& u, try_to_lock); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock ); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(boost::shared_lock<boost::shared_mutex>(m), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk(boost::move(lk0), boost::try_to_lock); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp new file mode 100644 index 000000000..3d2c2871b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(shared_lock<mutex_type>&&, +// const chrono::time_point<Clock, Duration>&); + +#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 <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::shared_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> + lk( boost::shared_lock<boost::shared_mutex>(m), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::shared_lock<boost::shared_mutex> lk0(m, boost::defer_lock); + lk0.release(); + boost::upgrade_lock<boost::shared_mutex> lk( boost::move(lk0), boost::chrono::steady_clock::now()+boost::chrono::milliseconds(1)); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp new file mode 100644 index 000000000..3d591d176 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock& operator=(unique_lock&& u); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + { + boost::unique_lock<boost::shared_mutex> lk0(m); + boost::upgrade_lock<boost::shared_mutex> lk( (boost::move(lk0))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(lk0.mutex() == 0); + BOOST_TEST(lk0.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk( (boost::unique_lock<boost::shared_mutex>(m))); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp new file mode 100644 index 000000000..1e634807d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// explicit upgrade_lock(Mutex& m); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::upgrade_lock<boost::shared_mutex> ul(m); + t1 = Clock::now(); + } +#else + //time_point t0 = Clock::now(); + //time_point t1; + { + boost::upgrade_lock<boost::shared_mutex> ul(m); + //t1 = Clock::now(); + } + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp new file mode 100644 index 000000000..4cf71476b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// upgrade_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); + +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(750)); + BOOST_TEST(lk.owns_lock() == true); + t1 = Clock::now(); +} + +void f2() +{ + t0 = Clock::now(); + boost::upgrade_lock<boost::shared_mutex> lk(m, Clock::now() + ms(250)); + BOOST_TEST(lk.owns_lock() == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp new file mode 100644 index 000000000..9a7fe26bf --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// upgrade_lock(mutex_type& m, try_to_lock_t); + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + BOOST_TEST(lk.owns_lock() == false); + } + for (;;) + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) { + t1 = Clock::now(); + break; + } + } + //m.unlock(); +#else +// time_point t0 = Clock::now(); +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } +// { +// boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); +// BOOST_TEST(lk.owns_lock() == false); +// } + for (;;) + { + boost::upgrade_lock<boost::shared_mutex> lk(m, boost::try_to_lock); + if (lk.owns_lock()) break; + } + //time_point t1 = Clock::now(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp new file mode 100644 index 000000000..2ff49ac96 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/lock_pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void lock(); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + boost::upgrade_lock < boost::shared_mutex > lk(m, boost::defer_lock); + t0 = Clock::now(); + lk.lock(); + t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#else + boost::upgrade_lock < boost::shared_mutex > lk(m, boost::defer_lock); + //time_point t0 = Clock::now(); + lk.lock(); + //time_point t1 = Clock::now(); + BOOST_TEST(lk.owns_lock() == true); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + lk.release(); + try + { + lk.lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp new file mode 100644 index 000000000..5f8f4f5fe --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_for_pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_for_called = false; + +typedef boost::chrono::milliseconds ms; + +struct shared_mutex +{ + template <class Rep, class Period> + bool try_lock_upgrade_for(const boost::chrono::duration<Rep, Period>& rel_time) + { + BOOST_TEST(rel_time == ms(5)); + try_lock_for_called = !try_lock_for_called; + return try_lock_for_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_for(ms(5)) == true); + BOOST_TEST(try_lock_for_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_for(ms(5)) == false); + BOOST_TEST(try_lock_for_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_for(ms(5)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp new file mode 100644 index 000000000..820fd71a3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_called = false; + +struct shared_mutex +{ + bool try_lock_upgrade() + { + try_lock_called = !try_lock_called; + return try_lock_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock() == true); + BOOST_TEST(try_lock_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock() == false); + BOOST_TEST(try_lock_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp new file mode 100644 index 000000000..1c53d6a5b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/try_lock_until_pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool try_lock_until_called = false; + +struct shared_mutex +{ + template <class Clock, class Duration> + bool try_lock_upgrade_until(const boost::chrono::time_point<Clock, Duration>& abs_time) + { + typedef boost::chrono::milliseconds ms; + BOOST_TEST(Clock::now() - abs_time < ms(5)); + try_lock_until_called = !try_lock_until_called; + return try_lock_until_called; + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + typedef boost::chrono::steady_clock Clock; + boost::upgrade_lock<shared_mutex> lk(m, boost::defer_lock); + BOOST_TEST(lk.try_lock_until(Clock::now()) == true); + BOOST_TEST(try_lock_until_called == true); + BOOST_TEST(lk.owns_lock() == true); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + lk.unlock(); + BOOST_TEST(lk.try_lock_until(Clock::now()) == false); + BOOST_TEST(try_lock_until_called == false); + BOOST_TEST(lk.owns_lock() == false); + lk.release(); + try + { + lk.try_lock_until(Clock::now()); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp new file mode 100644 index 000000000..bc49a0433 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/locking/unlock_pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/lock_types.hpp> +//#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +bool unlock_called = false; + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + unlock_called = true; + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m); + lk.unlock(); + BOOST_TEST(unlock_called == true); + BOOST_TEST(lk.owns_lock() == false); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + lk.release(); + try + { + lk.unlock(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::operation_not_permitted); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp new file mode 100644 index 000000000..4b0752ef5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/member_swap_pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void swap(upgrade_lock& u); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk1(m); + boost::upgrade_lock<shared_mutex> lk2; + lk1.swap(lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp new file mode 100644 index 000000000..c7ebaa271 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/non_member_swap_pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> +// void swap(upgrade_lock<Mutex>& x, upgrade_lock<Mutex>& y); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + void lock_upgrade() + { + } + void unlock_upgrade() + { + } +}; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk1(m); + boost::upgrade_lock<shared_mutex> lk2; + swap(lk1, lk2); + BOOST_TEST(lk1.mutex() == 0); + BOOST_TEST(lk1.owns_lock() == false); + BOOST_TEST(lk2.mutex() == &m); + BOOST_TEST(lk2.owns_lock() == true); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp new file mode 100644 index 000000000..226819446 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/mod/release_pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// void Mutex* release(); + +#include <boost/thread/lock_types.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct shared_mutex +{ + static int lock_count; + static int unlock_count; + void lock_upgrade() + { + ++lock_count; + } + void unlock_upgrade() + { + ++unlock_count; + } +}; + +int shared_mutex::lock_count = 0; +int shared_mutex::unlock_count = 0; + +shared_mutex m; + +int main() +{ + boost::upgrade_lock<shared_mutex> lk(m); + BOOST_TEST(lk.mutex() == &m); + BOOST_TEST(lk.owns_lock() == true); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + BOOST_TEST(lk.release() == &m); + BOOST_TEST(lk.mutex() == 0); + BOOST_TEST(lk.owns_lock() == false); + BOOST_TEST(shared_mutex::lock_count == 1); + BOOST_TEST(shared_mutex::unlock_count == 0); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp new file mode 100644 index 000000000..276cd0a93 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/mutex_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// Mutex *mutex() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.mutex() == 0); + boost::upgrade_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.mutex() == &m); + lk1.unlock(); + BOOST_TEST(lk1.mutex() == &m); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp new file mode 100644 index 000000000..4e722d174 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/op_bool_pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// explicit operator bool() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock < boost::shared_mutex > lk0; + BOOST_TEST(bool(lk0) == false); + boost::upgrade_lock < boost::shared_mutex > lk1(m); + BOOST_TEST(bool(lk1) == true); + lk1.unlock(); + BOOST_TEST(bool(lk1) == false); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp new file mode 100644 index 000000000..9d8b80d69 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/obs/owns_lock_pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/locks.hpp> + +// template <class Mutex> class upgrade_lock; + +// bool owns_lock() const; + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +boost::shared_mutex m; + +int main() +{ + boost::upgrade_lock<boost::shared_mutex> lk0; + BOOST_TEST(lk0.owns_lock() == false); + boost::upgrade_lock<boost::shared_mutex> lk1(m); + BOOST_TEST(lk1.owns_lock() == true); + lk1.unlock(); + BOOST_TEST(lk1.owns_lock() == false); + + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp new file mode 100644 index 000000000..876428e46 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/locks/upgrade_lock/types_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// <mutex> + +// template <class Mutex> +// class upgrade_lock +// { +// public: +// typedef Mutex mutex_type; +// ... +// }; + + +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_STATIC_ASSERT_MSG((boost::is_same<boost::upgrade_lock<boost::upgrade_mutex>::mutex_type, + boost::upgrade_mutex>::value), ""); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp new file mode 100644 index 000000000..fa1aff9b5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex& operator=(const mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + boost::mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp new file mode 100644 index 000000000..e6f6d6b88 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex(const mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + boost::mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp new file mode 100644 index 000000000..a911eefcf --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// mutex(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp new file mode 100644 index 000000000..f6bf74b56 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::mutex m0; + m0.lock(); + m0.lock(); + m0.unlock(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp new file mode 100644 index 000000000..9da22a59d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_compile_pass.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2017 Tom Hughes +// +// 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void pass() +{ + boost::mutex m0; + m0.lock(); + m0.unlock(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp new file mode 100644 index 000000000..94818fbad --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/lock_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// void lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp new file mode 100644 index 000000000..489ec375d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/native_handle_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// typedef pthread_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE + boost::mutex m; + boost::mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp new file mode 100644 index 000000000..05c2016cb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void fail() +{ + boost::mutex m0; + if (!m0.try_lock()) { + m0.unlock(); + } +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp new file mode 100644 index 000000000..e4cec906a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_compile_pass.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Tom Hughes +// +// 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +void pass() +{ + boost::mutex m0; + if (m0.try_lock()) { + m0.unlock(); + } +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp new file mode 100644 index 000000000..b973c1b23 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/mutex/try_lock_pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/mutex.hpp> + +// class mutex; + +// bool try_lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif + +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp new file mode 100644 index 000000000..e8b440abd --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex& operator=(const null_mutex&) = delete; + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + boost::null_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp new file mode 100644 index 000000000..66668f5e0 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex(const null_mutex&) = delete; + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + boost::null_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp new file mode 100644 index 000000000..343431a9e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// null_mutex(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::null_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp new file mode 100644 index 000000000..3c91e25f6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/lock_pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// void lock(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::null_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + time_point t0 = Clock::now(); + m.lock(); + time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 ; + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); + m.unlock(); + t.join(); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..1f5f5e9fc --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_for_pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + + +boost::null_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == true); + time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..cc51928bb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex.hpp> + +// class null_mutex; + +// bool try_lock(); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + + +boost::null_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock()); + time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + ns d = t1 - t0; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +#else + BOOST_TEST(m.try_lock()); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); + m.unlock(); + t.join(); + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..8a6985165 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/null_mutex/try_lock_until_pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/null_mutex> + +// class null_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/null_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::null_mutex m; + +typedef boost::chrono::steady_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == true); + time_point t1 = Clock::now(); + m.unlock(); + ns d = t1 - t0 ; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + + +int main() +{ + { + m.lock(); + boost::thread t(f1); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp new file mode 100644 index 000000000..ac7b80769 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp @@ -0,0 +1,297 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 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) + +// <boost/thread/once.hpp> + +// struct once_flag; + +// template<class Callable, class ...Args> +// void call_once(once_flag& flag, Callable&& func, Args&&... args); + +//#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#include <boost/thread/once.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#define BOOST_INIT_ONCE_INIT +#else +#define BOOST_INIT_ONCE_INIT =BOOST_ONCE_INIT +#endif + +typedef boost::chrono::milliseconds ms; + +boost::once_flag flg0 BOOST_INIT_ONCE_INIT; + +int init0_called = 0; + +void init0() +{ + boost::this_thread::sleep_for(ms(250)); + ++init0_called; +} + +void f0() +{ + boost::call_once(flg0, init0); +} + +boost::once_flag flg3 BOOST_INIT_ONCE_INIT; + +int init3_called = 0; +int init3_completed = 0; + +void init3() +{ + ++init3_called; + boost::this_thread::sleep_for(ms(250)); + if (init3_called == 1) + throw 1; + ++init3_completed; +} + +void f3() +{ + try + { + boost::call_once(flg3, init3); + } + catch (...) + { + } +} + +struct init1 +{ + static int called; + typedef void result_type; + + void operator()(int i) {called += i;} + void operator()(int i) const {called += i;} +}; + +int init1::called = 0; + +boost::once_flag flg1 BOOST_INIT_ONCE_INIT; + +void f1() +{ + boost::call_once(flg1, init1(), 1); +} + +boost::once_flag flg1_member BOOST_INIT_ONCE_INIT; + +struct init1_member +{ + static int called; + typedef void result_type; + void call(int i) { + called += i; + } +}; +int init1_member::called = 0; + +void f1_member_l() +{ + init1_member o; + int i=1; + boost::call_once(flg1_member, &init1_member::call, o, i); +} +void f1_member_r() +{ + init1_member o; + boost::call_once(flg1_member, &init1_member::call, o, 1); +} +struct init2 +{ + static int called; + typedef void result_type; + + void operator()(int i, int j) {called += i + j;} + void operator()(int i, int j) const {called += i + j;} +}; + +int init2::called = 0; + +boost::once_flag flg2 BOOST_INIT_ONCE_INIT; + +void f2() +{ + boost::call_once(flg2, init2(), 2, 3); + boost::call_once(flg2, init2(), 4, 5); +} + +boost::once_flag flg41 BOOST_INIT_ONCE_INIT; +boost::once_flag flg42 BOOST_INIT_ONCE_INIT; + +int init41_called = 0; +int init42_called = 0; + +void init42(); + +void init41() +{ + boost::this_thread::sleep_for(ms(250)); + ++init41_called; +} + +void init42() +{ + boost::this_thread::sleep_for(ms(250)); + ++init42_called; +} + +void f41() +{ + boost::call_once(flg41, init41); + boost::call_once(flg42, init42); +} + +void f42() +{ + boost::call_once(flg42, init42); + boost::call_once(flg41, init41); +} + +class MoveOnly +{ +public: + typedef void result_type; + + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()(BOOST_THREAD_RV_REF(MoveOnly)) + { + } + void operator()(int) + { + } + void operator()() + { + } +}; + + +struct id_string +{ + static boost::once_flag flag; + static void do_init(id_string & ) + {} + void operator()() + { + boost::call_once(flag, &id_string::do_init, boost::ref(*this)); + } +// void operator()(int,int) +// { +// // This should fail but works with gcc-4.6.3 +// //std::bind(&id_string::do_init, *this)(); +// std::bind(&id_string::do_init, std::ref(*this))(); +// } +// void operator()(int) const +// { +// //std::bind(&id_string::do_init, *this)(); +// } +}; + + +boost::once_flag id_string::flag BOOST_INIT_ONCE_INIT; + +int main() +{ + + // + { + id_string id; + id(); + //id(1,1); + } + // check basic functionality + { + boost::thread t0(f0); + boost::thread t1(f0); + t0.join(); + t1.join(); + BOOST_TEST(init0_called == 1); + } + // check basic exception safety + { + boost::thread t0(f3); + boost::thread t1(f3); + t0.join(); + t1.join(); + BOOST_TEST(init3_called == 2); + BOOST_TEST(init3_completed == 1); + } + // check deadlock avoidance + { + boost::thread t0(f41); + boost::thread t1(f42); + t0.join(); + t1.join(); + BOOST_TEST(init41_called == 1); + BOOST_TEST(init42_called == 1); + } + // check functors with 1 arg + { + boost::thread t0(f1); + boost::thread t1(f1); + t0.join(); + t1.join(); + BOOST_TEST(init1::called == 1); + } + // check functors with 2 args + { + boost::thread t0(f2); + boost::thread t1(f2); + t0.join(); + t1.join(); + BOOST_TEST(init2::called == 5); + } + + // check member function with 1 arg + { + boost::thread t0(f1_member_l); + boost::thread t1(f1_member_r); + t0.join(); + t1.join(); + BOOST_TEST(init1_member::called == 1); + } +#if defined BOOST_THREAD_PLATFORM_PTHREAD || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ > 40600) + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INVOKE + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly(), 1); + } + { + boost::once_flag f BOOST_INIT_ONCE_INIT; + boost::call_once(f, MoveOnly(), MoveOnly()); + } +#endif // BOOST_THREAD_PLATFORM_PTHREAD + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp new file mode 100644 index 000000000..05a628230 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/queue_views/single_thread_pass.cpp @@ -0,0 +1,468 @@ +// Copyright (C) 2014 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) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// sync_queue(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/concurrent_queues/sync_queue.hpp> +#include <boost/thread/concurrent_queues/queue_adaptor.hpp> +#include <boost/thread/concurrent_queues/queue_views.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class non_copyable +{ + int val; +public: + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES +BOOST_STATIC_ASSERT( ! boost::is_copy_constructible<non_copyable>::value ); +BOOST_STATIC_ASSERT( boost::has_move_emulation_enabled<non_copyable>::value ); +#endif + +int main() +{ + + { + // default queue invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // default queue invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + + { + // empty queue try_pull fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue push rvalue/non_copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue push rvalue/non_copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > q; + //boost::sync_queue<non_copyable> q; + //boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue push rvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#if 0 + { + // empty queue try_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + int i=0; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + +#if 0 + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_back<non_copyable> q(sq); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue try_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue try_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue nonblocking_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue nonblocking_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1900) + { + // 1-element queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<non_copyable> > sq; + boost::queue_front<non_copyable> q(sq); + non_copyable nc1(1); + sq.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // closed invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed invariants + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_back<int> q(sq); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + sq.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::queue_adaptor<boost::sync_queue<int> > sq; + boost::queue_front<int> q(sq); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp new file mode 100644 index 000000000..041102e91 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex& operator=(const recursive_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + boost::recursive_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp new file mode 100644 index 000000000..932422d15 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex(const recursive_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + boost::recursive_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp new file mode 100644 index 000000000..6b6199720 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// recursive_mutex(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp new file mode 100644 index 000000000..a5410d25e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// void lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::recursive_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..b784f24e5 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// typedef pthread_recursive_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE + boost::recursive_mutex m; + boost::recursive_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..0f8fe822a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_mutex/try_lock_pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_mutex; + +// bool try_lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../timming.hpp" + +boost::recursive_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); +// BOOST_TEST(!m.try_lock()); +// BOOST_TEST(!m.try_lock()); +// BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp new file mode 100644 index 000000000..48b9cc47d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/assign_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + boost::recursive_timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp new file mode 100644 index 000000000..b4e96c7ac --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex(const recursive_timed_mutex&) = delete; + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + boost::recursive_timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp new file mode 100644 index 000000000..1e75b7b04 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// recursive_timed_mutex(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::recursive_timed_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp new file mode 100644 index 000000000..bd0646f64 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// void lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <iostream> +#include "../../../timming.hpp" + +boost::recursive_timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.lock(); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..bcd375e53 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// typedef pthread_recursive_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ +#if defined BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE + boost::recursive_timed_mutex m; + boost::recursive_timed_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..c7f6d2b0b --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::recursive_timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +} + +void f2() +{ + time_point t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + time_point t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..3874d6853 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex.hpp> + +// class recursive_timed_mutex; + +// bool try_lock(); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::recursive_timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + BOOST_TEST(m.try_lock()); + m.unlock(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..238467204 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/recursive_mutex> + +// class recursive_timed_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::recursive_timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp new file mode 100644 index 000000000..ee6446d7e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// shared_mutex& operator=(const shared_mutex&) = delete; + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + boost::shared_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp new file mode 100644 index 000000000..9627f9f66 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/copy_fail.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// shared_mutex(const shared_mutex&) = delete; + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + boost::shared_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp new file mode 100644 index 000000000..730c9cafc --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/timed_mutex.hpp> + +// class shared_mutex; + +// shared_mutex(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::shared_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp new file mode 100644 index 000000000..0b53fb275 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/lock_pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// void lock(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..bc06576ec --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_for_pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..515589a6f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// bool try_lock(); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..dd8a1a816 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/shared_mutex/try_lock_until_pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// 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) + +// <boost/thread/shared_mutex.hpp> + +// class shared_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::shared_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp new file mode 100644 index 000000000..9975a995a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp @@ -0,0 +1,252 @@ +// Copyright (C) 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) + +// <boost/thread/sync_bounded_queue.hpp> + +// class sync_queue<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_bounded_queue.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct call_push +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + + call_push(boost::sync_bounded_queue<int> &q, boost::barrier &go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_.count_down_and_wait(); + q_.push(42); + + } +}; + +struct call_push_2 +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + boost::barrier& end_; + + call_push_2(boost::sync_bounded_queue<int> &q, boost::barrier &go, boost::barrier &end) : + q_(q), go_(go), end_(end) + { + } + typedef void result_type; + void operator()() + { + go_.count_down_and_wait(); + q_.push(42); + end_.count_down_and_wait(); + + } +}; + +struct call_pull +{ + boost::sync_bounded_queue<int> &q_; + boost::barrier& go_; + + call_pull(boost::sync_bounded_queue<int> &q, boost::barrier &go) : + q_(q), go_(go) + { + } + typedef int result_type; + int operator()() + { + go_.count_down_and_wait(); + return q_.pull(); + } +}; + +void test_concurrent_push_and_pull_on_empty_queue() +{ + boost::sync_bounded_queue<int> q(4); + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() + { + go.wait(); + q.push(42); + } +#else + call_push(q,go) +#endif + ); + pull_done=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull(q,go) +#endif + ); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_push_on_empty_queue() +{ + boost::sync_bounded_queue<int> q(4); + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() + { + go.wait(); + q.push(42); + } +#else + call_push(q,go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_push_on_full_queue() +{ + const unsigned int size = 2; + boost::sync_bounded_queue<int> q(size); + const unsigned int n = 2*size; + boost::barrier go(n); + boost::barrier end(size+1); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go,&end]() + { + go.wait(); + q.push(42); + end.wait(); + } +#else + call_push_2(q,go,end) +#endif + ); + + end.wait(); + BOOST_TEST(!q.empty()); + BOOST_TEST(q.full()); + for (unsigned int i =0; i< size; ++i) + BOOST_TEST_EQ(q.pull(), 42); + end.wait(); + + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< size; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} +void test_concurrent_pull_on_queue() +{ + boost::sync_bounded_queue<int> q(4); + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull(q,go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_and_pull_on_empty_queue(); + test_concurrent_push_on_empty_queue(); + test_concurrent_push_on_full_queue(); + test_concurrent_pull_on_queue(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp new file mode 100644 index 000000000..201e0bc13 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp @@ -0,0 +1,600 @@ +// Copyright (C) 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) + +// <boost/thread/sync_bounded_queue.hpp> + +// class sync_bounded_queue<T> + +// sync_bounded_queue(); + +#define BOOST_THREAD_VERSION 4 +//#define BOOST_THREAD_QUEUE_DEPRECATE_OLD + +#include <boost/thread/sync_bounded_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable() {} + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + +int main() +{ + + { + // default queue invariants + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST_EQ(q.capacity(), 2u); + BOOST_TEST(! q.closed()); + } +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST(! q.try_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(! q.try_pull()); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + q.push(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(3); + q.push(1); + BOOST_TEST_EQ(q.size(), 1u); + q.push(2); + BOOST_TEST_EQ(q.size(), 2u); + q.push(2); + BOOST_TEST_EQ(q.size(), 3u); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST(! q.closed()); + } + { + // empty queue push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i=1; + BOOST_TEST(q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(q.try_push(boost::no_block, 1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(q.try_push(boost::no_block, boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push(boost::move(nc)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + BOOST_TEST(q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + int i; + BOOST_TEST(q.try_pull(boost::no_block, i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + boost::shared_ptr<int> i = q.try_pull(); + BOOST_TEST_EQ(*i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push rvalue fails + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.push(2); + BOOST_TEST(! q.try_push(3)); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push succeeds + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.push(2); + BOOST_TEST(q.try_pull()); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_bounded_queue<int> q(2); + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } +#endif + { + // empty queue try_pull fails + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue succeeds + boost::sync_bounded_queue<int> q(3); + q.push_back(1); + BOOST_TEST_EQ(q.size(), 1u); + q.push_back(2); + BOOST_TEST_EQ(q.size(), 2u); + q.push_back(3); + BOOST_TEST_EQ(q.size(), 3u); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST(! q.closed()); + } + { + // empty queue push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back( 1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push rvalue succeeds + boost::sync_bounded_queue<int> q(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push rvalue succeeds + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue wait_push value succeeds + boost::sync_bounded_queue<int> q(2); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<non_copyable> q(2); + non_copyable nc(1); + q.push_back(boost::move(nc)); + non_copyable nc2(2); + q.pull_front(nc2); + BOOST_TEST_EQ(nc, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i = q.pull_front(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // full queue try_push rvalue fails + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.push_back(2); + BOOST_TEST(boost::queue_op_status::full == q.try_push_back(3)); + BOOST_TEST(! q.empty()); + BOOST_TEST( q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_bounded_queue<int> q(2); + q.close(); + try { + q.push_back(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // closed empty queue try_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue nonblocking_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.nonblocking_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.close(); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::sync_bounded_queue<int> q(2); + q.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front closed + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + { + // closed queue wait_push_back fails + boost::sync_bounded_queue<int> q(2); + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_push_back(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp new file mode 100644 index 000000000..703c54f40 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/multi_thread_pass.cpp @@ -0,0 +1,256 @@ +// Copyright (C) 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) + +// <boost/thread/concurrent_queues/sync_deque.hpp> + +// class sync_deque<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/concurrent_queues/sync_deque.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +template <typename ValueType> +struct call_push_back +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_push_back(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_->count_down_and_wait(); + q_->push_back(42); + } +}; + +template <typename ValueType> +struct call_pull_front +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef ValueType result_type; + ValueType operator()() + { + go_->count_down_and_wait(); + return q_->pull_front(); + } +}; + +template <typename ValueType> +struct call_wait_pull_front +{ + boost::sync_deque<ValueType> *q_; + boost::barrier *go_; + + call_wait_pull_front(boost::sync_deque<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef boost::queue_op_status result_type; + boost::queue_op_status operator()(ValueType& v) + { + go_->wait(); + return q_->wait_pull_front(v); + } +}; + +void test_concurrent_push_back_and_pull_front_on_empty_queue() +{ + boost::sync_deque<int> q; + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, + call_push_back<int>(&q,&go)); + pull_done=boost::async(boost::launch::async, + call_pull_front<int>(&q,&go)); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void test_concurrent_push_back_and_wait_pull_front_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull_front<int>(&q,&go), + boost::ref(results[i])); + + for (unsigned int i =0; i< n; ++i) + q.push_back(42); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success); + BOOST_TEST_EQ(results[i], 42); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_wait_pull_front_and_close_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull_front<int>(&q,&go), + boost::ref(results[i])); + + q.close(); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} +#endif + +void test_concurrent_push_back_on_empty_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, + call_push_back<int>(&q,&go)); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull_front(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_pull_front_on_queue() +{ + boost::sync_deque<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push_back(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull_front(); + } +#else + call_pull_front<int>(&q,&go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_back_and_pull_front_on_empty_queue(); +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + test_concurrent_push_back_and_wait_pull_front_on_empty_queue(); + test_concurrent_wait_pull_front_and_close_on_empty_queue(); +#endif + test_concurrent_push_back_on_empty_queue(); + test_concurrent_pull_front_on_queue(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp new file mode 100644 index 000000000..5170bcf61 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_deque/single_thread_pass.cpp @@ -0,0 +1,403 @@ +// Copyright (C) 2013,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) + +// <boost/thread/concurrent_queues/sync_deque.hpp> + +// class sync_deque<T> + +// sync_deque(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/concurrent_queues/sync_deque.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + + +int main() +{ + + { + // default queue invariants + boost::sync_deque<int> q; + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_pull fails + boost::sync_deque<int> q; + int i; + BOOST_TEST( boost::queue_op_status::empty == q.try_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push rvalue/copyable succeeds + boost::sync_deque<int> q; + q.push_back(1); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue/copyable succeeds + boost::sync_deque<int> q; + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_deque<non_copyable> q; + q.push_back(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + q.push_back(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue push rvalue succeeds + boost::sync_deque<int> q; + q.push_back(1); + q.push_back(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::sync_deque<int> q; + int i; + q.push_back(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push_back(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue try_push lvalue succeeds + boost::sync_deque<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push_back(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_deque<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue nonblocking_push_back rvalue/non-copyable succeeds + boost::sync_deque<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push_back(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc2(2); + q.pull_front(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i = q.pull_front(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc = q.pull_front(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull_front succeed + boost::sync_deque<non_copyable> q; + non_copyable nc1(1); + q.push_back(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_deque<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_deque<int> q; + q.close(); + try { + q.push_back(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_deque<int> q; + q.push_back(1); + q.close(); + int i; + q.pull_front(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull_front succeed + boost::sync_deque<int> q; + q.push_back(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull_front(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull_front fails + boost::sync_deque<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull_front(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp new file mode 100644 index 000000000..92e183079 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp @@ -0,0 +1,219 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <exception> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> +#include <boost/thread/concurrent_queues/sync_priority_queue.hpp> + +#include <boost/core/lightweight_test.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +typedef boost::concurrent::sync_priority_queue<int> sync_pq; + +int call_pull(sync_pq* q, boost::barrier* go) +{ + go->wait(); + return q->pull(); + +} + +void call_push(sync_pq* q, boost::barrier* go, int val) +{ + go->wait(); + q->push(val); +} + +void test_pull(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + for(int i = 0; i < n; i++) + { + pq.push(i); + } + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(n)); + pq.close(); + BOOST_TEST(pq.closed()); + boost::barrier b(n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_pull, &pq, &b)); + } + tg.join_all(); + BOOST_TEST(pq.empty()); +} + +void test_push(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + + boost::barrier b(n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_push, &pq, &b, i)); + } + tg.join_all(); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(n)); +} + +void test_both(const int n) +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + + boost::barrier b(2*n); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + tg.create_thread(boost::bind(call_pull, &pq, &b)); + tg.create_thread(boost::bind(call_push, &pq, &b, i)); + } + tg.join_all(); + BOOST_TEST(pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); +} + +void push_range(sync_pq* q, const int begin, const int end) +{ + for(int i = begin; i < end; i++) + q->push(i); +} + +void atomic_pull(sync_pq* q, boost::atomic<int>* sum) +{ + while(1) + { + try{ + const int val = q->pull(); + sum->fetch_add(val); + } + catch(std::exception& ){ + break; + } + } +} + +/** + * This test computes the sum of the first N integers upto $limit using + * $n threads for the push operation and $n threads for the pull and count + * operation. The push operation push a range of numbers on the queue while + * the pull operation pull from the queue and increments an atomic int. + * At the end of execution the value of atomic<int> $sum should be the same + * as n*(n+1)/2 as this is the closed form solution to this problem. + */ +void compute_sum(const int n) +{ + const int limit = 1000; + sync_pq pq; + BOOST_TEST(pq.empty()); + boost::atomic<int> sum(0); + boost::thread_group tg1; + boost::thread_group tg2; + for(int i = 0; i < n; i++) + { + tg1.create_thread(boost::bind(push_range, &pq, i*(limit/n)+1, (i+1)*(limit/n)+1)); + tg2.create_thread(boost::bind(atomic_pull, &pq, &sum)); + } + tg1.join_all(); + pq.close(); //Wait until all enqueuing is done before closing. + BOOST_TEST(pq.closed()); + tg2.join_all(); + BOOST_TEST(pq.empty()); + BOOST_TEST_EQ(sum.load(), limit*(limit+1)/2); +} + +void move_between_queues(sync_pq* q1, sync_pq* q2) +{ + while(1){ + try{ + const int val = q1->pull(); + q2->push(val); + } + catch(std::exception& ){ + break; + } + } +} + +/** + * This test computes the sum of the first N integers upto $limit by moving + * numbers between 2 sync_priority_queues. A range of numbers are pushed onto + * one queue by $n threads while $n threads pull from this queue and push onto + * another sync_pq. At the end the main thread ensures the the values in the + * second queue are in proper order and then sums all the values from this + * queue. The sum should match n*(n+1)/2, the closed form solution to this + * problem. + */ +void sum_with_moving(const int n) +{ + const int limit = 1000; + sync_pq pq1; + sync_pq pq2; + BOOST_TEST(pq1.empty()); + BOOST_TEST(pq2.empty()); + boost::thread_group tg1; + boost::thread_group tg2; + for(int i = 0; i < n; i++) + { + tg1.create_thread(boost::bind(push_range, &pq1, i*(limit/n)+1, (i+1)*(limit/n)+1)); + tg2.create_thread(boost::bind(move_between_queues, &pq1, &pq2)); + } + tg1.join_all(); + pq1.close(); //Wait until all enqueuing is done before closing. + BOOST_TEST(pq1.closed()); + tg2.join_all(); + BOOST_TEST(pq1.empty()); + BOOST_TEST(!pq2.empty()); + int sum = 0; + for(int i = 1000; i > 0; i--){ + const int val = pq2.pull(); + BOOST_TEST_EQ(i,val); + sum += val; + } + BOOST_TEST(pq2.empty()); + BOOST_TEST_EQ(sum, limit*(limit+1)/2); +} + +int main() +{ + for(int i = 1; i <= 64; i *= 2) + { + test_pull(i); + test_push(i); + test_both(i); + } + //These numbers must divide 1000 + compute_sum(1); + compute_sum(4); + compute_sum(10); + compute_sum(25); + compute_sum(50); + sum_with_moving(1); + sum_with_moving(4); + sum_with_moving(10); + sum_with_moving(25); + sum_with_moving(50); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp new file mode 100644 index 000000000..b51827731 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/pq_single_thread_pass.cpp @@ -0,0 +1,429 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014,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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/thread/concurrent_queues/sync_priority_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +using namespace boost::chrono; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; + +typedef boost::concurrent::sync_priority_queue<int> sync_pq; + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + bool operator <(const non_copyable& other) const + { + return val < other.val; + } +}; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void test_pull_for() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_for(milliseconds(500), val); + ns d = steady_clock::now() - start - milliseconds(500); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::timeout == st); +} + +void test_pull_until() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val); + ns d = steady_clock::now() - start - milliseconds(500); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::timeout == st); +} + +void test_nonblocking_pull() +{ + sync_pq pq; + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::empty == st); +} + +void test_pull_for_when_not_empty() +{ + sync_pq pq; + pq.push(1); + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_for(milliseconds(500), val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::success == st); + BOOST_TEST(1 == val); +} + +void test_pull_until_when_not_empty() +{ + sync_pq pq; + pq.push(1); + steady_clock::time_point start = steady_clock::now(); + int val; + boost::queue_op_status st = pq.pull_until(start + milliseconds(500), val); + ns d = steady_clock::now() - start; + BOOST_THREAD_TEST_IT(d, ns(max_diff)); + BOOST_TEST(boost::queue_op_status::success == st); + BOOST_TEST(1 == val); +} + +int main() +{ + sync_pq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + pq.push(i); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + boost::queue_op_status succ = pq.try_push(i); + BOOST_TEST(succ == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 10; i > 5; i--){ + int val = pq.pull(); + BOOST_TEST_EQ(val, i); + } + +// for(int i = 5; i > 0; i--){ +// boost::optional<int> val = pq.try_pull(); +// BOOST_TEST(val); +// BOOST_TEST_EQ(*val, i); +// } + +// BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); + + test_pull_for(); + test_pull_until(); + test_nonblocking_pull(); + + test_pull_for_when_not_empty(); + //test_pull_until_when_not_empty(); + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + //fixme + // empty queue try_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // empty queue try_push lvalue succeeds + boost::concurrent::sync_priority_queue<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#if 0 + { + // empty queue try_push rvalue succeeds + boost::concurrent::sync_priority_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + i=q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc2(2); + nc2=q.pull(); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // 1-element queue try_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue try_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue nonblocking_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue nonblocking_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + { + // 1-element queue wait_pull succeed + boost::concurrent::sync_priority_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } +#endif + + { + // closed invariants + boost::concurrent::sync_priority_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::concurrent::sync_priority_queue<int> q; + q.close(); + try { + q.push(1); + BOOST_TEST(false); // fixme + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + q.close(); + int i; + i=q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::concurrent::sync_priority_queue<int> q; + q.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::concurrent::sync_priority_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp new file mode 100644 index 000000000..77656f8b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_multi_thread_pass.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2019 Austin Beer +// Copyright (C) 2019 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> + +#include <boost/core/lightweight_test.hpp> +#include "../../../timming.hpp" + +using namespace boost::chrono; + +typedef boost::concurrent::sync_timed_queue<int> sync_tq; + +const int cnt = 5; + +void call_push(sync_tq* q, const steady_clock::time_point start) +{ + // push elements onto the queue every 500 milliseconds but with a decreasing delay each time + for (int i = 0; i < cnt; ++i) + { + boost::this_thread::sleep_until(start + milliseconds(i * 500)); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + q->push(i, expected); + } +} + +void call_pull(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull(j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void call_pull_until(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull_until(steady_clock::now() + hours(1), j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void call_pull_for(sync_tq* q, const steady_clock::time_point start) +{ + // pull elements off of the queue (earliest element first) + for (int i = cnt - 1; i >= 0; --i) + { + int j; + q->pull_for(hours(1), j); + BOOST_TEST_EQ(i, j); + const steady_clock::time_point expected = start + milliseconds(i * 500) + seconds(cnt - i); + BOOST_TEST_GE(steady_clock::now(), expected - milliseconds(BOOST_THREAD_TEST_TIME_MS)); + BOOST_TEST_LE(steady_clock::now(), expected + milliseconds(BOOST_THREAD_TEST_TIME_MS)); + } +} + +void test_push_while_pull() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +void test_push_while_pull_until() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull_until, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +void test_push_while_pull_for() +{ + sync_tq tq; + BOOST_TEST(tq.empty()); + boost::thread_group tg; + const steady_clock::time_point start = steady_clock::now(); + tg.create_thread(boost::bind(call_push, &tq, start)); + tg.create_thread(boost::bind(call_pull_for, &tq, start)); + tg.join_all(); + BOOST_TEST(tq.empty()); +} + +int main() +{ + test_push_while_pull(); + test_push_while_pull_until(); + test_push_while_pull_for(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp new file mode 100644 index 000000000..dd4dfc17f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_pq/tq_single_thread_pass.cpp @@ -0,0 +1,155 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <boost/function.hpp> +#include <boost/thread/concurrent_queues/sync_timed_queue.hpp> +#include <boost/thread/executors/work.hpp> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + +typedef boost::concurrent::sync_timed_queue<int> sync_tq; + +void test_all() +{ + sync_tq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + pq.push(i, milliseconds(i*100)); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + pq.push(i,steady_clock::now() + milliseconds(i*100)); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 1; i <= 10; i++){ + int val = pq.pull(); + BOOST_TEST_EQ(val, i); + } + + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + BOOST_TEST(boost::queue_op_status::empty == st); + + BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); +} + +void test_all_with_try() +{ + sync_tq pq; + BOOST_TEST(pq.empty()); + BOOST_TEST(!pq.closed()); + BOOST_TEST_EQ(pq.size(), std::size_t(0)); + + for(int i = 1; i <= 5; i++){ + boost::queue_op_status st = pq.try_push(i, milliseconds(i*100)); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 6; i <= 10; i++){ + boost::queue_op_status st = pq.try_push(i,steady_clock::now() + milliseconds(i*100)); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST(!pq.empty()); + BOOST_TEST_EQ(pq.size(), std::size_t(i)); + } + + for(int i = 1; i <= 10; i++){ + int val=0; + boost::queue_op_status st = pq.wait_pull(val); + BOOST_TEST(st == boost::queue_op_status::success ); + BOOST_TEST_EQ(val, i); + } + + int val; + boost::queue_op_status st = pq.nonblocking_pull(val); + BOOST_TEST(st == boost::queue_op_status::empty ); + + BOOST_TEST(pq.empty()); + pq.close(); + BOOST_TEST(pq.closed()); +} + +void func(steady_clock::time_point pushed, steady_clock::duration dur) +{ + BOOST_TEST(pushed + dur <= steady_clock::now()); +} +void func2() +{ + BOOST_TEST(false); +} + +/** + * This test ensures that when items come of the front of the queue + * that at least $dur has elapsed. + */ +void test_deque_times() +{ + boost::concurrent::sync_timed_queue<boost::function<void()> > tq; + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + boost::function<void()> fn = boost::bind(func, steady_clock::now(), d); + tq.push(fn, d); + } + while(!tq.empty()) + { + boost::function<void()> fn = tq.pull(); + fn(); + } +} + +/** + * This test ensures that when items come of the front of the queue + * that at least $dur has elapsed. + */ +#if 0 +void test_deque_times2() +{ + boost::concurrent::sync_timed_queue<boost::executors::work> tq; + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + tq.push(func2, d); + } + while(!tq.empty()) + { + boost::executors::work fn = tq.pull(); + fn(); + } +} +#endif + +int main() +{ + test_all(); + test_all_with_try(); + test_deque_times(); + //test_deque_times2(); // rt fails + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp new file mode 100644 index 000000000..556ca68e9 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/multi_thread_pass.cpp @@ -0,0 +1,256 @@ +// Copyright (C) 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) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// push || pull; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_queue.hpp> +#include <boost/thread/future.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> + +template <typename ValueType> +struct call_push +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_push(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef void result_type; + void operator()() + { + go_->count_down_and_wait(); + q_->push(42); + } +}; + +template <typename ValueType> +struct call_pull +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef ValueType result_type; + ValueType operator()() + { + go_->count_down_and_wait(); + return q_->pull(); + } +}; + +template <typename ValueType> +struct call_wait_pull +{ + boost::sync_queue<ValueType> *q_; + boost::barrier *go_; + + call_wait_pull(boost::sync_queue<ValueType> *q, boost::barrier *go) : + q_(q), go_(go) + { + } + typedef boost::queue_op_status result_type; + boost::queue_op_status operator()(ValueType& v) + { + go_->wait(); + return q_->wait_pull(v); + } +}; + +void test_concurrent_push_and_pull_on_empty_queue() +{ + boost::sync_queue<int> q; + + boost::barrier go(2); + + boost::future<void> push_done; + boost::future<int> pull_done; + + try + { + push_done=boost::async(boost::launch::async, + call_push<int>(&q,&go)); + pull_done=boost::async(boost::launch::async, + call_pull<int>(&q,&go)); + + push_done.get(); + BOOST_TEST_EQ(pull_done.get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +void test_concurrent_push_and_wait_pull_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull<int>(&q,&go), + boost::ref(results[i])); + + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::success); + BOOST_TEST_EQ(results[i], 42); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_wait_pull_and_close_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<boost::queue_op_status> pull_done[n]; + int results[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, + call_wait_pull<int>(&q,&go), + boost::ref(results[i])); + + q.close(); + + for (unsigned int i = 0; i < n; ++i) { + BOOST_TEST(pull_done[i].get() == boost::queue_op_status::closed); + } + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} +#endif + +void test_concurrent_push_on_empty_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + boost::future<void> push_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + push_done[i]=boost::async(boost::launch::async, + call_push<int>(&q,&go)); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + for (unsigned int i = 0; i < n; ++i) + push_done[i].get(); + + } + catch (...) + { + BOOST_TEST(false); + } + try + { + BOOST_TEST(!q.empty()); + for (unsigned int i =0; i< n; ++i) + BOOST_TEST_EQ(q.pull(), 42); + BOOST_TEST(q.empty()); + + } + catch (...) + { + BOOST_TEST(false); + } +} + +void test_concurrent_pull_on_queue() +{ + boost::sync_queue<int> q; + const unsigned int n = 3; + boost::barrier go(n); + + boost::future<int> pull_done[n]; + + try + { + for (unsigned int i =0; i< n; ++i) + q.push(42); + + for (unsigned int i =0; i< n; ++i) + pull_done[i]=boost::async(boost::launch::async, +#if ! defined BOOST_NO_CXX11_LAMBDAS + [&q,&go]() -> int + { + go.wait(); + return q.pull(); + } +#else + call_pull<int>(&q,&go) +#endif + ); + + for (unsigned int i = 0; i < n; ++i) + BOOST_TEST_EQ(pull_done[i].get(), 42); + BOOST_TEST(q.empty()); + } + catch (...) + { + BOOST_TEST(false); + } +} + +int main() +{ + test_concurrent_push_and_pull_on_empty_queue(); +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + test_concurrent_push_and_wait_pull_on_empty_queue(); + test_concurrent_wait_pull_and_close_on_empty_queue(); +#endif + test_concurrent_push_on_empty_queue(); + test_concurrent_pull_on_queue(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp new file mode 100644 index 000000000..8f47ec82a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/sync_queue/single_thread_pass.cpp @@ -0,0 +1,374 @@ +// Copyright (C) 2013,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) + +// <boost/thread/sync_queue.hpp> + +// class sync_queue<T> + +// sync_queue(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/sync_queue.hpp> + +#include <boost/detail/lightweight_test.hpp> + +class non_copyable +{ + BOOST_THREAD_MOVABLE_ONLY(non_copyable) + int val; +public: + non_copyable(int v) : val(v){} + non_copyable(BOOST_RV_REF(non_copyable) x): val(x.val) {} + non_copyable& operator=(BOOST_RV_REF(non_copyable) x) { val=x.val; return *this; } + bool operator==(non_copyable const& x) const {return val==x.val;} + template <typename OSTREAM> + friend OSTREAM& operator <<(OSTREAM& os, non_copyable const&x ) + { + os << x.val; + return os; + } + +}; + + + +int main() +{ + + { + // default queue invariants + boost::sync_queue<int> q; + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_queue<non_copyable> q; + q.push(non_copyable(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue push rvalue/non_copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + q.push(boost::move(nc)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue push rvalue succeeds + boost::sync_queue<int> q; + q.push(1); + q.push(2); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 2u); + BOOST_TEST(! q.closed()); + } + { + // empty queue push lvalue succeeds + boost::sync_queue<int> q; + int i; + q.push(i); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue/copyable succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.try_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success ==q.try_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue try_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.try_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + + { + // empty queue try_push lvalue succeeds + boost::sync_queue<int> q; + int i=1; + BOOST_TEST(boost::queue_op_status::success == q.try_push(i)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // empty queue try_push rvalue succeeds + boost::sync_queue<int> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(1)); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(non_copyable(1))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } +#endif + { + // empty queue nonblocking_push rvalue/non-copyable succeeds + boost::sync_queue<non_copyable> q; + non_copyable nc(1); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_push(boost::move(nc))); + BOOST_TEST(! q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 1u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc2(2); + q.pull(nc2); + BOOST_TEST_EQ(nc1, nc2); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<int> q; + q.push(1); + int i = q.pull(); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc = q.pull(); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.try_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue try_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.try_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue nonblocking_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.nonblocking_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<int> q; + q.push(1); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + { + // 1-element queue wait_pull succeed + boost::sync_queue<non_copyable> q; + non_copyable nc1(1); + q.push(boost::move(nc1)); + non_copyable nc(2); + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(nc)); + BOOST_TEST_EQ(nc, nc1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(! q.closed()); + } + + { + // closed invariants + boost::sync_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed queue push fails + boost::sync_queue<int> q; + q.close(); + try { + q.push(1); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + } + { + // 1-element closed queue pull succeed + boost::sync_queue<int> q; + q.push(1); + q.close(); + int i; + q.pull(i); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // 1-element closed queue wait_pull succeed + boost::sync_queue<int> q; + q.push(1); + q.close(); + int i; + BOOST_TEST(boost::queue_op_status::success == q.wait_pull(i)); + BOOST_TEST_EQ(i, 1); + BOOST_TEST(q.empty()); + BOOST_TEST(! q.full()); + BOOST_TEST_EQ(q.size(), 0u); + BOOST_TEST(q.closed()); + } + { + // closed empty queue wait_pull fails + boost::sync_queue<int> q; + q.close(); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + int i; + BOOST_TEST(boost::queue_op_status::closed == q.wait_pull(i)); + BOOST_TEST(q.empty()); + BOOST_TEST(q.closed()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp new file mode 100644 index 000000000..f1ed8be4a --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp @@ -0,0 +1,144 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// template <typename F> +// inline typename boost::result_of<F(value_type&)>::type +// operator()(BOOST_THREAD_RV_REF(F) fct); +// template <typename F> +// inline typename boost::result_of<F(value_type const&)>::type +// operator()(BOOST_THREAD_RV_REF(F) fct) const; + +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +void c(S const& s) +{ + BOOST_TEST(s.f()==1); +} + +void nc(S & s) +{ + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); +} + +struct cfctr { + typedef void result_type; + void operator()(S const& s) const { + BOOST_TEST(s.f()==1); + } +}; +struct ncfctr { + typedef void result_type; + void operator()(S& s) const { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + } +}; + +struct cfctr3 { + typedef void result_type; + BOOST_THREAD_MOVABLE_ONLY(cfctr3) + cfctr3() + {} + cfctr3(BOOST_THREAD_RV_REF(cfctr3)) + {} + void operator()(S const& s) const { + BOOST_TEST(s.f()==1); + } +}; +struct ncfctr3 { + typedef void result_type; + BOOST_THREAD_MOVABLE_ONLY(ncfctr3) + ncfctr3() + {} + ncfctr3(BOOST_THREAD_RV_REF(ncfctr3)) + {} + void operator()(S& s) const { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + } +}; + +cfctr3 make_cfctr3() { + return BOOST_THREAD_MAKE_RV_REF(cfctr3()); +} + +ncfctr3 make_ncfctr3() { + return BOOST_THREAD_MAKE_RV_REF(ncfctr3()); +} + +int main() +{ + { + boost::synchronized_value<S> v; + v(&nc); + v(&c); + } + { + const boost::synchronized_value<S> v; + v(&c); + } + { + boost::synchronized_value<S> v; + v(ncfctr()); + } + { + const boost::synchronized_value<S> v; + v(cfctr()); + } + { + boost::synchronized_value<S> v; + ncfctr fct; + v(fct); + } + { + const boost::synchronized_value<S> v; + cfctr fct; + v(fct); + } + { + boost::synchronized_value<S> v; + v(make_ncfctr3()); + } + { + const boost::synchronized_value<S> v; + v(make_cfctr3()); + } +#if ! defined BOOST_NO_CXX11_LAMBDAS + { + boost::synchronized_value<S> v; + v([](S& s) { + BOOST_TEST(s.f()==1); + BOOST_TEST(s.g()==1); + }); + } + { + const boost::synchronized_value<S> v; + v([](S const& s) { + BOOST_TEST(s.f()==1); + }); + } +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp new file mode 100644 index 000000000..3b43f8f90 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_assign_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(T const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v; + v = i; + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp new file mode 100644 index 000000000..e395c57aa --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_T_ctor_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(T const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v(i); + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp new file mode 100644 index 000000000..d4e80b0ce --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_assign_pass.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(synchronized_value const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v1(i); + boost::synchronized_value<int> v2; + v2 = v1; + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp new file mode 100644 index 000000000..13fcf6d80 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/copy_ctor_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(synchronized_value const&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + int i = 1; + boost::synchronized_value<int> v1(i); + boost::synchronized_value<int> v2(v1); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp new file mode 100644 index 000000000..7b4095650 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/default_ctor_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int, boost::mutex > f; + } + { + boost::synchronized_value<int, boost::timed_mutex> f; + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp new file mode 100644 index 000000000..09b8e89d2 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/indirect_pass.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// strict_lock_ptr<T,M> operator->(); +// const_strict_lock_ptr<T,M> operator->() const; + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +int main() +{ + { + boost::synchronized_value<S> v; + BOOST_TEST(v->f()==1); + BOOST_TEST(v->g()==1); + } + { + const boost::synchronized_value<S> v; + BOOST_TEST(v->f()==1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp new file mode 100644 index 000000000..146ed2e51 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_assign_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(T &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v; + v = 1; + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp new file mode 100644 index 000000000..564d57da8 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_T_ctor_pass.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(T &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v(1); + BOOST_TEST(v.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp new file mode 100644 index 000000000..818216382 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_assign_pass.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value& operator=(synchronized_value &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2; + v2 = boost::move(v1); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp new file mode 100644 index 000000000..7250e896f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/move_ctor_pass.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// synchronized_value(synchronized_value &&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2(boost::move(v1)); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp new file mode 100644 index 000000000..801b514d6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// void swap(synchronized_value&,synchronized_value&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + int v2(2); + boost::swap(v1,v2); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2 == 1); + } + { + boost::synchronized_value<int> v1(1); + int v2(2); + boost::swap(v2,v1); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2 == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp new file mode 100644 index 000000000..c52069ff3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/swap_pass.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// void swap(synchronized_value&,synchronized_value&); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + + { + boost::synchronized_value<int> v1(1); + boost::synchronized_value<int> v2(2); + swap(v1,v2); + BOOST_TEST(v1.value() == 2); + BOOST_TEST(v2.value() == 1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp new file mode 100644 index 000000000..af24d79b6 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 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) + +// <boost/thread/synchronized_value.hpp> + +// class synchronized_value<T,M> + +// strict_lock_ptr<T,M> synchronize(); +// const_strict_lock_ptr<T,M> synchronize() const; + + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/synchronized_value.hpp> + +#include <boost/detail/lightweight_test.hpp> + +struct S { + int f() const {return 1;} + int g() {return 1;} +}; + +int main() +{ + { + boost::synchronized_value<S> v; + boost::strict_lock_ptr<S> ptr = v.synchronize(); + BOOST_TEST(ptr->f()==1); + BOOST_TEST(ptr->g()==1); + } + { + const boost::synchronized_value<S> v; + boost::const_strict_lock_ptr<S> ptr = v.synchronize(); + BOOST_TEST(ptr->f()==1); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp new file mode 100644 index 000000000..49188e130 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/assign_fail.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex& operator=(const timed_mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + boost::timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp new file mode 100644 index 000000000..ed0a4c955 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/copy_fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex(const timed_mutex&) = delete; + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + boost::timed_mutex m1(m0); +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp new file mode 100644 index 000000000..6b7c6f2b3 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/default_pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// timed_mutex(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::timed_mutex m0; + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp new file mode 100644 index 000000000..8d2733e1f --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/lock_pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// void lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +boost::timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + m.lock(); + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + m.lock(); + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp new file mode 100644 index 000000000..b203e5d91 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/native_handle_pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// typedef pthread_timed_mutex_t* native_handle_type; +// native_handle_type native_handle(); + +#include <boost/thread/mutex.hpp> +#include <boost/detail/lightweight_test.hpp> + + +int main() +{ +#if defined BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE + boost::timed_mutex m; + boost::timed_mutex::native_handle_type h = m.native_handle(); + BOOST_TEST(h); +#else +#error "Test not applicable: BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE not defined for this platform as not supported" +#endif + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp new file mode 100644 index 000000000..94d790e0e --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_for_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// template <class Rep, class Period> +// bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_for(ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp new file mode 100644 index 000000000..96e99e7f7 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// bool try_lock(); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + + +boost::timed_mutex m; + +#if defined BOOST_THREAD_USES_CHRONO +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; +#else +#endif + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f() +{ +#if defined BOOST_THREAD_USES_CHRONO + t0 = Clock::now(); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + t1 = Clock::now(); + m.unlock(); +#else + //time_point t0 = Clock::now(); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + //BOOST_TEST(!m.try_lock()); + while (!m.try_lock()) + ; + //time_point t1 = Clock::now(); + m.unlock(); + //ns d = t1 - t0 - ms(250); + //BOOST_TEST(d < max_diff); +#endif +} + +int main() +{ + m.lock(); + boost::thread t(f); +#if defined BOOST_THREAD_USES_CHRONO + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); +#else +#endif + m.unlock(); + t.join(); + +#if defined BOOST_THREAD_USES_CHRONO + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); +#endif + + return boost::report_errors(); +} + + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp new file mode 100644 index 000000000..958a42d03 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/timed_mutex/try_lock_until_pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/timed_mutex.hpp> + +// class timed_mutex; + +// template <class Clock, class Duration> +// bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "../../../timming.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +boost::timed_mutex m; + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point time_point; +typedef Clock::duration duration; +typedef boost::chrono::milliseconds ms; +typedef boost::chrono::nanoseconds ns; +time_point t0; +time_point t1; + +const ms max_diff(BOOST_THREAD_TEST_TIME_MS); + +void f1() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(750)) == true); + t1 = Clock::now(); + m.unlock(); +} + +void f2() +{ + t0 = Clock::now(); + BOOST_TEST(m.try_lock_until(Clock::now() + ms(250)) == false); + t1 = Clock::now(); + ns d = t1 - t0 - ms(250); + BOOST_THREAD_TEST_IT(d, ns(max_diff)); +} + +int main() +{ + { + m.lock(); + boost::thread t(f1); + time_point t2 = Clock::now(); + boost::this_thread::sleep_for(ms(250)); + time_point t3 = Clock::now(); + m.unlock(); + t.join(); + + ns sleep_time = t3 - t2; + ns d_ns = t1 - t0 - sleep_time; + ms d_ms = boost::chrono::duration_cast<boost::chrono::milliseconds>(d_ns); + // BOOST_TEST_GE(d_ms.count(), 0); + BOOST_THREAD_TEST_IT(d_ms, max_diff); + BOOST_THREAD_TEST_IT(d_ns, ns(max_diff)); + } + { + m.lock(); + boost::thread t(f2); + boost::this_thread::sleep_for(ms(750)); + m.unlock(); + t.join(); + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp new file mode 100644 index 000000000..9ec0dfdfb --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_bind.cpp @@ -0,0 +1,145 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 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) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> +#include <boost/bind/bind.hpp> + +class Foo { + public: + Foo(int value): value_(value) { + } + + int func(int a, int b) const { + BOOST_TEST(a == 1); + BOOST_TEST(b == 31); + return a + b + value_; + } + + int func_ref(int& a) const { + a = 133; + return 36; + } + + void func_ref(int& a, int& b, int* c) const { + BOOST_TEST(value_ == 3); + a = 567; + b = 897; + *c = 345; + } + + private: + int value_; +}; + +void test_bind() { + boost::mutex m; + + Foo foo(2); + + int res_bind = boost::with_lock_guard( + m, + boost::bind(&Foo::func, foo, 1, 31) + ); + BOOST_TEST(res_bind == 34); + + int a = 0; + int res_bind_ref = boost::with_lock_guard( + m, + boost::bind(&Foo::func_ref, foo, boost::ref(a)) + ); + BOOST_TEST(res_bind_ref == 36); + BOOST_TEST(a == 133); + + a = 0; + int b = 0; + int c = 0; + Foo boo(3); + boost::with_lock_guard( + m, boost::bind(&Foo::func_ref, boo, boost::ref(a), boost::ref(b), &c) + ); + BOOST_TEST(a == 567); + BOOST_TEST(b == 897); + BOOST_TEST(c == 345); +} + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +void test_bind_non_const() { + std::cout << "c++11 variadic templates disabled" << std::endl; +} +#else + +// calling non-const bind methods supported only with c++11 variadic templates +class Boo { + public: + Boo(int value): value_(value) { + } + + int func(int a, int b) { + BOOST_TEST(a == 7); + BOOST_TEST(b == 3); + return a - b + value_; + } + + int func_ref(int& a) { + a = 598; + return 23; + } + + void func_ref(int& a, int& b, int* c) { + BOOST_TEST(value_ == 67); + a = 111; + b = 222; + *c = 333; + } + + private: + int value_; +}; + +void test_bind_non_const() { + boost::mutex m; + + Boo boo(20); + + int res_bind = boost::with_lock_guard( + m, + boost::bind(&Boo::func, boo, 7, 3) + ); + BOOST_TEST(res_bind == 24); + + int a = 0; + int res_bind_ref = boost::with_lock_guard( + m, + boost::bind(&Boo::func_ref, boo, boost::ref(a)) + ); + BOOST_TEST(res_bind_ref == 23); + BOOST_TEST(a == 598); + + a = 0; + int b = 0; + int c = 0; + Boo foo(67); + boost::with_lock_guard( + m, boost::bind(&Boo::func_ref, foo, boost::ref(a), boost::ref(b), &c) + ); + BOOST_TEST(a == 111); + BOOST_TEST(b == 222); + BOOST_TEST(c == 333); +} +#endif + +int main() { + test_bind(); + test_bind_non_const(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp new file mode 100644 index 000000000..8eda53dea --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_lambda.cpp @@ -0,0 +1,59 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 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) + +// See www.boost.org/libs/thread for documentation. + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <iostream> // std::cout +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> + +#if defined(BOOST_NO_CXX11_LAMBDAS) || (defined BOOST_MSVC && _MSC_VER < 1700) +void test_lambda() { + std::cout << "C++11 lambda disabled" << std::endl; +} +#else +void test_lambda() { + boost::mutex m; + int res_1 = boost::with_lock_guard( + m, + [](int a) { + BOOST_TEST(a == 13); + return a + 3; + }, + 13 + ); + BOOST_TEST(res_1 == 16); + + int v = 0; + int res_2 = boost::with_lock_guard( + m, + [&v](int a) { + BOOST_TEST(a == 55); + v = 15; + return 45; + }, + 55 + ); + BOOST_TEST(res_2 == 45); + BOOST_TEST(v == 15); +} +#endif + +int main() { + std::cout << std::boolalpha; + test_lambda(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp new file mode 100644 index 000000000..2c685790d --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_move.cpp @@ -0,0 +1,110 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 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) + +// See www.boost.org/libs/thread for documentation. + +#define BOOST_THREAD_VERSION 4 + +#include <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> + +class Foo { + public: + explicit Foo(int a) : a_(a) { + } + + Foo(BOOST_RV_REF(Foo) foo) : a_(foo.a_) { + BOOST_ASSERT(&foo != this); + foo.a_ = 0; + } + + Foo& operator=(BOOST_RV_REF(Foo) foo) { + BOOST_ASSERT(&foo != this); + a_ = foo.a_; + foo.a_ = 0; + return *this; + } + + int get() const { + return a_; + } + + private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(Foo) + + int a_; +}; + +template <class T1, class T2> +bool func_with_2_arg(BOOST_FWD_REF(T1) arg_1, BOOST_FWD_REF(T2) arg_2) { + BOOST_TEST(arg_1.get() == 3); + BOOST_TEST(arg_2.get() == 767); + return false; +} + +void test_movable() { + boost::mutex m; + + Foo foo_1(3); + Foo foo_2(767); + + bool res = boost::with_lock_guard( + m, &func_with_2_arg<Foo, Foo>, boost::move(foo_1), boost::move(foo_2) + ); + BOOST_TEST(!res); +} + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +void test_real_movable() { + std::cout << "c++11 move emulated" << std::endl; +} +#else +// test real one +class Boo { + public: + Boo(int a) : a_(a) { + } + + Boo(Boo&& boo) : a_(boo.a_) { + BOOST_ASSERT(&boo != this); + boo.a_ = 0; + } + + int get() const { + return a_; + } + + BOOST_DELETED_FUNCTION(Boo(Boo&)) + BOOST_DELETED_FUNCTION(Boo& operator=(Boo&)) + BOOST_DELETED_FUNCTION(Boo& operator=(Boo&&)) + private: + int a_; +}; + +void func_with_3_arg(Boo&& boo_1, Boo&& boo_2, Boo&& boo_3) { + BOOST_TEST(boo_1.get() == 11); + BOOST_TEST(boo_2.get() == 12); + BOOST_TEST(boo_3.get() == 13); +} + +void test_real_movable() { + boost::mutex m; + + Boo boo_3(13); + + boost::with_lock_guard( + m, func_with_3_arg, Boo(11), Boo(12), boost::move(boo_3) + ); +} +#endif + +int main() { + test_movable(); + test_real_movable(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp new file mode 100644 index 000000000..dc9c44455 --- /dev/null +++ b/src/boost/libs/thread/test/sync/mutual_exclusion/with_lock_guard/with_lock_guard_simple.cpp @@ -0,0 +1,139 @@ +// (C) Copyright 2013 Ruslan Baratov +// (C) Copyright 2013 Ruslan Baratov +// +// 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 <boost/detail/lightweight_test.hpp> // BOOST_TEST + +#include <boost/thread/mutex.hpp> +#include <boost/thread/with_lock_guard.hpp> +#include <boost/ref.hpp> + +void func_with_0_arg() { +} + +void func_with_1_arg(int arg_1) { + BOOST_TEST(arg_1 == 3); +} + +bool func_with_2_arg(int arg_1, bool arg_2) { + BOOST_TEST(arg_1 == 3); + BOOST_TEST(arg_2 == true); + return !arg_2; +} + +int func_with_3_arg(int arg_1, bool arg_2, const char* arg_3) { + BOOST_TEST(arg_1 == 13); + BOOST_TEST(arg_2 == false); + BOOST_TEST(std::string(arg_3) == "message for func with 3 arg"); + return 12; +} + +const char* func_with_4_arg(int arg_1, bool arg_2, int* arg_3, int& arg_4) { + BOOST_TEST(arg_1 == 23); + BOOST_TEST(arg_2 == false); + *arg_3 = 128; + arg_4 = 456; + return "hello"; +} + +void test_simple() { + boost::mutex m; + + // #0 + boost::with_lock_guard(m, func_with_0_arg); + + // #1 + boost::with_lock_guard(m, func_with_1_arg, 3); + + // #2 + bool res2 = boost::with_lock_guard(m, func_with_2_arg, 3, true); + BOOST_TEST(res2 == false); + + // #3 + int arg1 = 13; + const char* mes = "message for func with 3 arg"; + int res3 = boost::with_lock_guard(m, func_with_3_arg, arg1, false, mes); + BOOST_TEST(res3 == 12); + + // #4 + int arg3 = 0; + int arg4 = 0; + const char* res4 = boost::with_lock_guard( + m, + func_with_4_arg, + 23, + false, + &arg3, + boost::ref(arg4) + ); + BOOST_TEST(arg3 == 128); + BOOST_TEST(arg4 == 456); + BOOST_TEST(std::string(res4) == "hello"); +} + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +void test_variadic_templates() { + std::cout << "C++11 variadic templates disabled" << std::endl; +} +#else +int func_with_5_args(int a1, char a2, int& a3, bool* a4, bool a5) { + BOOST_TEST(a1 == 12); + BOOST_TEST(a2 == 'x'); + BOOST_TEST(a5 == false); + a3 = 135; + *a4 = false; + return 45; +} + +int func_with_6_args(int a1, char a2, int& a3, bool* a4, int&& a5, bool a6) { + BOOST_TEST(a1 == 12); + BOOST_TEST(a2 == 'N'); + BOOST_TEST(a5 == 2 || a5 == 13); + BOOST_TEST(a6 == false); + a3 = 200; + *a4 = true; + return 888; +} + +void test_variadic_templates() { + boost::mutex m; + + int a3 = 0; + bool a4 = true; + int res5 = boost::with_lock_guard( + m, func_with_5_args, 12, 'x', a3, &a4, false + ); + BOOST_TEST(a3 == 135); + BOOST_TEST(a4 == false); + BOOST_TEST(res5 == 45); + + int res6 = boost::with_lock_guard( + m, func_with_6_args, 12, 'N', a3, &a4, 2, false + ); + BOOST_TEST(a3 == 200); + BOOST_TEST(a4 == true); + BOOST_TEST(res6 == 888); + + a3 = 0; + a4 = false; + int a5 = 13; + int res6_move = boost::with_lock_guard( + m, func_with_6_args, 12, 'N', a3, &a4, boost::move(a5), false + ); + BOOST_TEST(a3 == 200); + BOOST_TEST(a4 == true); + BOOST_TEST_EQ(res6_move, 888); +} +#endif + +int main() { + test_simple(); + test_variadic_templates(); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test.mcp b/src/boost/libs/thread/test/test.mcp Binary files differnew file mode 100644 index 000000000..f27f0b97b --- /dev/null +++ b/src/boost/libs/thread/test/test.mcp diff --git a/src/boost/libs/thread/test/test_10340.cpp b/src/boost/libs/thread/test/test_10340.cpp new file mode 100644 index 000000000..5311e8210 --- /dev/null +++ b/src/boost/libs/thread/test/test_10340.cpp @@ -0,0 +1,28 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> + +struct foo +{ + foo(int i_): i(i_) {} + int i; +}; + +int main() +{ + boost::promise<foo> p; + const foo f(42); + p.set_value(f); + + // Clearly a const future ref isn't much use, but I needed to + // prove the problem wasn't me trying to copy a unique_future + + const boost::future<foo>& fut = boost::make_ready_future( foo(42) ); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_10963.cpp b/src/boost/libs/thread/test/test_10963.cpp new file mode 100644 index 000000000..1ec8d6cfc --- /dev/null +++ b/src/boost/libs/thread/test/test_10963.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) + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <cassert> +#include <boost/thread/executors/basic_thread_pool.hpp> + + +struct TestCallback +{ + typedef boost::future<void> result_type; + + result_type operator()(boost::future<void> future) const + { + assert(future.is_ready()); + future.get(); + return boost::make_ready_future(); + } + + result_type operator()(boost::future<boost::future<void> > future) const + { + assert(future.is_ready()); + future.get(); + return boost::make_ready_future(); + } +}; + +int main() +{ +#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + { + boost::promise<void> test_promise; + boost::future<void> test_future(test_promise.get_future()); + auto f1 = test_future.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value); + } + { + boost::basic_thread_pool executor; + boost::promise<void> test_promise; + boost::future<void> test_future(test_promise.get_future()); + auto f1 = test_future.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value); + + } +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_10964.cpp b/src/boost/libs/thread/test/test_10964.cpp new file mode 100644 index 000000000..48ee5cd95 --- /dev/null +++ b/src/boost/libs/thread/test/test_10964.cpp @@ -0,0 +1,191 @@ +// Copyright (C) 2015 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> +#include <boost/static_assert.hpp> +#include <cassert> +#include <iostream> +#include <boost/thread/executors/basic_thread_pool.hpp> + +struct TestCallback +{ + typedef boost::future<void> result_type; + + result_type operator()(boost::future<void> future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + future.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return boost::make_ready_future(); + } + + result_type operator()(boost::future<boost::future<void> > future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.get().is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + //boost::future<void> ff = future.get(); + + return boost::make_ready_future(); + } + result_type operator()(boost::shared_future<void> future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + future.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return boost::make_ready_future(); + } + + result_type operator()(boost::shared_future<boost::future<void> > future) const + { + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + assert(future.get().is_ready()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + //boost::future<void> ff = future.get(); + + return boost::make_ready_future(); + } +}; + +void p1() +{ +} + +int main() +{ + const int number_of_tests = 2; + (void)(number_of_tests); + +#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + f1.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + auto f2 = f1.unwrap(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + f2.wait(); + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + boost::future<void> f2 = f1.get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.unwrap(); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::make_ready_future().then( + TestCallback()).unwrap().then(TestCallback()).get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::future<void> f = boost::async(p1); + f.then( + TestCallback()).unwrap().then(TestCallback()).get(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + auto f1 = boost::make_ready_future().then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor; + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f3 = f1.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } +#if 1 + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + // fixme + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor(2); + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f1.valid()) << std::endl; + auto f2 = f1.unwrap(); + std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f2.valid()) << std::endl; + + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } +#endif + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + for (int i=0; i< number_of_tests; i++) + { + boost::basic_thread_pool executor; + + auto f1 = boost::make_ready_future().then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value); + auto f2 = f1.unwrap(); + BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value); + auto f3 = f2.then(executor, TestCallback()); + BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value); + f3.wait(); + } + std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_11053.cpp b/src/boost/libs/thread/test/test_11053.cpp new file mode 100644 index 000000000..a8b6dfa97 --- /dev/null +++ b/src/boost/libs/thread/test/test_11053.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2015 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 <boost/thread.hpp> +#include <boost/thread/tss.hpp> +#include <boost/shared_ptr.hpp> +#include <iostream> + +struct A +{ + void DoWork() + { + std::cout << "A: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new WorkSpace()); + // do not very much + for (size_t i = 0; i < 10; ++i) + m_ptr->a += 10; + } + +private: + struct WorkSpace + { + int a; + WorkSpace() : a(0) {} + }; + boost::thread_specific_ptr<WorkSpace> m_ptr; +}; + +struct B +{ + void DoWork() + { + std::cout << "B: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new A()); + m_ptr->DoWork(); + } +private: + boost::thread_specific_ptr<A> m_ptr; +}; + +struct C +{ + void DoWork() + { + std::cout << "C: doing work\n"; + if (!m_ptr.get()) + m_ptr.reset(new B()); + m_ptr->DoWork(); + } +private: + boost::thread_specific_ptr<B> m_ptr; +}; + +int main(int ac, char** av) +{ + std::cout << "test starting\n"; + boost::shared_ptr<C> p_C(new C); + boost::thread cWorker(&C::DoWork, p_C); + cWorker.join(); + std::cout << "test stopping\n"; + return 0; +} + + + diff --git a/src/boost/libs/thread/test/test_11256.cpp b/src/boost/libs/thread/test/test_11256.cpp new file mode 100644 index 000000000..13002f867 --- /dev/null +++ b/src/boost/libs/thread/test/test_11256.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 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 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread.hpp> +#include <boost/thread/thread_pool.hpp> +#include <cassert> + +auto createFuture() +{ + boost::promise<void> promise; + promise.set_value(); + return promise.get_future(); +} + +auto stepOne(boost::basic_thread_pool &executor) +{ + auto sendFuture = createFuture(); + auto wrappedFuture = sendFuture.then(executor, [](auto f) mutable { + return createFuture(); + }); + + return wrappedFuture.unwrap(); +} + +auto stepTwo(boost::basic_thread_pool &executor) +{ + auto future = stepOne(executor); + return future.then(executor, [](auto f) { + assert(f.is_ready()); + }); +} + +int main() +{ + boost::basic_thread_pool executor{1}; + stepTwo(executor).get(); +} diff --git a/src/boost/libs/thread/test/test_11266.cpp b/src/boost/libs/thread/test/test_11266.cpp new file mode 100644 index 000000000..0f736783a --- /dev/null +++ b/src/boost/libs/thread/test/test_11266.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2015 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 <boost/thread/future.hpp> + +void func(int) { } + +int main() +{ +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + boost::packaged_task<void(int)> task{func}; + } + { + boost::packaged_task<void(int)> task{func}; + + task(0); + } + { + boost::packaged_task<void(int)> task{func}; + int x = 0; + task(x); + } +#endif +} diff --git a/src/boost/libs/thread/test/test_11499.cpp b/src/boost/libs/thread/test/test_11499.cpp new file mode 100644 index 000000000..2fe07ae88 --- /dev/null +++ b/src/boost/libs/thread/test/test_11499.cpp @@ -0,0 +1,56 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/shared_mutex.hpp> +#include <thread> +#include <mutex> +#include <shared_mutex> +#include <atomic> +#include <vector> + +using MutexT = boost::shared_mutex; +using ReaderLockT = std::lock_guard<MutexT>; +using WriterLockT = std::shared_lock<MutexT>; + +MutexT gMutex; +std::atomic<bool> running(true); + + +void myread() +{ + long reads = 0; + while (running && reads < 100000) + { + ReaderLockT lock(gMutex); + std::this_thread::yield(); + ++reads; + } +} + +int main() +{ + using namespace std; + + vector<thread> threads; + for (int i = 0; i < 256; ++i) + { + threads.emplace_back(thread(myread)); + } + +// string str; +// +// getline(std::cin, str); + running = false; + + for (auto& thread : threads) + { + thread.join(); + } + + return 0; +} + diff --git a/src/boost/libs/thread/test/test_11611.cpp b/src/boost/libs/thread/test/test_11611.cpp new file mode 100644 index 000000000..0a38b4b27 --- /dev/null +++ b/src/boost/libs/thread/test/test_11611.cpp @@ -0,0 +1,66 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> + +#define BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_EXECUTORS +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#if __cplusplus >= 201103L +#include <boost/thread/executors/loop_executor.hpp> +#include <boost/thread/executors/serial_executor.hpp> +#endif +#include <boost/thread/thread.hpp> +#include <boost/atomic.hpp> + +using namespace std; + +int main() +{ +#if __cplusplus >= 201103L + static std::size_t const nWorks = 100000; + boost::atomic<unsigned> execCount(0u); + boost::loop_executor ex; + + boost::thread t([&ex]() + { + ex.loop(); + }); + + { + boost::serial_executor serial(ex); + + for (size_t i = 0; i < nWorks; i++) + serial.submit([i, &execCount] { + //std::cout << i << "."; + ++execCount; + }); + + serial.close(); + } + unsigned const cnt = execCount.load(); + if (cnt != nWorks) { + // Since the serial_executor is closed, all work should have been done, + // even though the loop_executor ex is not. + std::cerr << "Only " << cnt << " of " << nWorks << " works executed!\n"; + return 1; + } + + if (ex.try_executing_one()) { + std::cerr + << "loop_executor::try_executing_one suceeded on closed executor!\n"; + return 1; + } + + ex.close(); + + t.join(); + std::cout << "end\n" << std::endl; +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_11796.cpp b/src/boost/libs/thread/test/test_11796.cpp new file mode 100644 index 000000000..6aab1af79 --- /dev/null +++ b/src/boost/libs/thread/test/test_11796.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2015 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 <boost/thread.hpp> +#include <boost/chrono.hpp> +#include <iostream> + +boost::thread th; +int main() +{ + + for (auto ti = 0; ti < 1000; ti++) + { + th = boost::thread([ti]() + { + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + std::cout << ti << std::endl; + }); + } + std::string st; + + std::cin >> st; + +// for (int i = 0; i < 10; ++i) { +// std::cout << "." << i << std::endl; +// boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); +// } + th.join(); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_11818.cpp b/src/boost/libs/thread/test/test_11818.cpp new file mode 100644 index 000000000..0d2b381de --- /dev/null +++ b/src/boost/libs/thread/test/test_11818.cpp @@ -0,0 +1,64 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <thread> + +int main() +{ + + { + boost::promise<int> promise; + boost::future<int> future = promise.get_future(); + + boost::future<int> result = + future.then + ( + boost::launch::deferred, + [](boost::future<int> && f) + { + std::cout << std::this_thread::get_id() << ": callback" << std::endl; + std::cout << "The value is: " << f.get() << std::endl; + return f.get(); + } + ); + + // We could not reach here. + std::cout << std::this_thread::get_id() << ": function" << std::endl; + + promise.set_value(0); + } + + { + boost::promise<int> promise; + boost::shared_future<int> future = promise.get_future().share(); + + boost::future<int> result = + future.then + ( + boost::launch::deferred, + [](boost::shared_future<int> && f) + { + std::cout << std::this_thread::get_id() << ": callback" << std::endl; + std::cout << "The value is: " << f.get() << std::endl; + return f.get(); + } + ); + + // We could not reach here. + std::cout << std::this_thread::get_id() << ": function" << std::endl; + + promise.set_value(0); + } + + return 0; +} diff --git a/src/boost/libs/thread/test/test_12293.cpp b/src/boost/libs/thread/test/test_12293.cpp new file mode 100644 index 000000000..0b305edc6 --- /dev/null +++ b/src/boost/libs/thread/test/test_12293.cpp @@ -0,0 +1,64 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + +// BoostFutureTest.cpp : Defines the entry point for the console application. +// + +#include <iostream> + +// boost version 1.60.0 +// has the following set. +#define BOOST_THREAD_VERSION 4 +// #define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/future.hpp> + + +int main() +{ +#if __cplusplus >= 201103L + + int value = 0; + int tmpValue = 0; + boost::promise<void> promise1; + boost::promise<void> promise2; + + auto future1 = promise1.get_future(); + + auto waitFuture = future1.then([&tmpValue, &promise2](boost::future<void> future){ + assert(future.is_ready()); // this works correctly and is ready. + + auto fut = boost::async(boost::launch::async, [&promise2, &tmpValue](){ + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + tmpValue = 1; + promise2.set_value(); + std::cout << "Step 2 "<< std::endl; // should print 1 but prints 0 + }); + std::cout << "Step 1 "<< std::endl; // should print 1 but prints 0 + + return promise2.get_future(); + //return ; + }).then([&value, &tmpValue](boost::future<boost::future<void>> future){ + //}).then([&value, &tmpValue](boost::future<void> future){ + // error: no matching function for call to ‘boost::future<boost::future<void> >::then(main()::<lambda(boost::future<void>)>)’ + // as expected + + assert(future.is_ready()); // this doesn't work correctly and is not ready. + + + value = tmpValue; + }); + + + promise1.set_value(); + waitFuture.wait(); + + std::cout << "value = " << value << std::endl; // should print 1 but prints 0 +#endif + return 0; +} + diff --git a/src/boost/libs/thread/test/test_12949.cpp b/src/boost/libs/thread/test/test_12949.cpp new file mode 100644 index 000000000..2b6235238 --- /dev/null +++ b/src/boost/libs/thread/test/test_12949.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2017 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 <boost/thread/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +void f() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); // ** +} +int main() +{ + + return 0; +} + diff --git a/src/boost/libs/thread/test/test_13480b.cpp b/src/boost/libs/thread/test/test_13480b.cpp new file mode 100644 index 000000000..3f89145d8 --- /dev/null +++ b/src/boost/libs/thread/test/test_13480b.cpp @@ -0,0 +1,77 @@ +// comment if you want to see the boost::move issue +#define BOOST_THREAD_VERSION 3 + +#include <boost/type_traits/is_same.hpp> +#include <boost/variant/detail/apply_visitor_binary.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> + +#define WANT_BUILD_TO_FAIL +#ifdef WANT_BUILD_TO_FAIL +#include <boost/thread.hpp> +#endif + +class AType +{ + +}; + +class BType +{ +}; + +typedef boost::shared_ptr<AType> IATypePtr; +typedef boost::shared_ptr<BType> IBTypePtr; + +typedef boost::variant<IATypePtr, IBTypePtr> ABVar; + +struct ServiceTimeTableEvent +{ +public: + + ServiceTimeTableEvent(ABVar abType) + : m_abType{ abType } + {} + + inline ABVar const& GetABType() const { return m_abType; } + inline ABVar & GetABType() { return m_abType; } + +private: + ABVar m_abType; +}; + +class ab_are_equals + : public boost::static_visitor<bool> +{ +public: + template<typename T, typename U> + bool operator()(T, U) const + { + return false; // cannot compare different types + } + template<typename T> + bool operator()(T lhs, T rhs) const + { + return lhs == rhs; + } +}; + +int main(int argc, char* argv[]) +{ + + auto aTypePtr = IATypePtr{ new AType }; + auto bTypePtr = IBTypePtr{ new BType }; + + ABVar aType = aTypePtr; + ABVar bType = bTypePtr; + + ServiceTimeTableEvent timeTableEvent1{ aType }; + ServiceTimeTableEvent timeTableEvent2{ bType }; + + auto xx = boost::apply_visitor(ab_are_equals(), timeTableEvent1.GetABType(), timeTableEvent2.GetABType()); + xx = boost::apply_visitor(ab_are_equals(), timeTableEvent1.GetABType(), timeTableEvent1.GetABType());; + xx = boost::apply_visitor(ab_are_equals(), timeTableEvent2.GetABType(), timeTableEvent2.GetABType());; +} + + diff --git a/src/boost/libs/thread/test/test_13561.cpp b/src/boost/libs/thread/test/test_13561.cpp new file mode 100644 index 000000000..b72f593d6 --- /dev/null +++ b/src/boost/libs/thread/test/test_13561.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2018 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 <boost/thread/detail/nullary_function.hpp> +#include <boost/system/detail/error_code.ipp> + +int main(int argc, char* argv[]) +{ + boost::detail::nullary_function<void ()> f1; + auto f2 = f1; +} + + diff --git a/src/boost/libs/thread/test/test_2309.cpp b/src/boost/libs/thread/test/test_2309.cpp new file mode 100644 index 000000000..c3208f97f --- /dev/null +++ b/src/boost/libs/thread/test/test_2309.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2010 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 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +//#define BOOST_TEST_MODULE Boost.Threads: 2309 +//#include <boost/test/unit_test.hpp> + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/detail/lightweight_test.hpp> + + using namespace std; + + boost::mutex mutex_; + + void perform() + { + try + { + boost::this_thread::sleep(boost::posix_time::seconds(100)); + } + catch (boost::thread_interrupted& interrupt) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " got interrupted" << endl; + throw(interrupt); + } + catch (std::exception& e) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " caught std::exception" << e.what() << endl; + } + catch (...) + { + boost::unique_lock<boost::mutex> lock(mutex_); + cerr << "Thread " << boost::this_thread::get_id() << " caught something else" << endl; + } + } + + void ticket_2309_test() + { + try + { + boost::thread_group threads; + + for (int i = 0; i < 2; ++i) + { + threads.create_thread(perform); + } + + //boost::this_thread::sleep(1); + threads.interrupt_all(); + threads.join_all(); + } + catch (...) + { + BOOST_TEST(false && "exception raised"); + } + } + + int main() + { + + ticket_2309_test(); + } + diff --git a/src/boost/libs/thread/test/test_2501.cpp b/src/boost/libs/thread/test/test_2501.cpp new file mode 100644 index 000000000..c654e7272 --- /dev/null +++ b/src/boost/libs/thread/test/test_2501.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2010 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 <boost/thread/shared_mutex.hpp> +#include <boost/thread/locks.hpp> + +int main() { + + boost::shared_mutex mtx; boost::upgrade_lock<boost::shared_mutex> lk(mtx); + + boost::upgrade_to_unique_lock<boost::shared_mutex> lk2(lk); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_2741.cpp b/src/boost/libs/thread/test/test_2741.cpp new file mode 100644 index 000000000..349d7d2ae --- /dev/null +++ b/src/boost/libs/thread/test/test_2741.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2008 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_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: thread attributes test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/bind/bind.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> + +#include <iostream> +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +int test_value; +#ifdef PTHREAD_STACK_MIN +#define MY_PTHREAD_STACK PTHREAD_STACK_MIN +#else +#define MY_PTHREAD_STACK 4*0x4000 +#endif +void simple_thread() +{ + test_value = 999; +} + +BOOST_AUTO_TEST_CASE(test_native_handle) +{ + + boost::thread_attributes attrs; + + boost::thread_attributes::native_handle_type* h = attrs.native_handle(); + (void)(h); // unused +#if defined(BOOST_THREAD_PLATFORM_WIN32) + // ... window version +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) + + int k = pthread_attr_setstacksize(h, MY_PTHREAD_STACK); + std::cout << k << std::endl; + BOOST_CHECK(!pthread_attr_setstacksize(h, MY_PTHREAD_STACK)); + std::size_t res; + BOOST_CHECK(!pthread_attr_getstacksize(h, &res)); + BOOST_CHECK(res >= (MY_PTHREAD_STACK)); +#else +#error "Boost thread unavailable on this platform" +#endif + +} + +BOOST_AUTO_TEST_CASE(test_stack_size) +{ + boost::thread_attributes attrs; + + attrs.set_stack_size(0x4000); + BOOST_CHECK(attrs.get_stack_size() >= 0x4000); + +} + +void do_test_creation_with_attrs() +{ + test_value = 0; + boost::thread_attributes attrs; + attrs.set_stack_size(0x4000); + boost::thread thrd(attrs, &simple_thread); + thrd.join(); + BOOST_CHECK_EQUAL(test_value, 999); +} + +BOOST_AUTO_TEST_CASE(test_creation_with_attrs) +{ + timed_test(&do_test_creation_with_attrs, 1); +} + + diff --git a/src/boost/libs/thread/test/test_3628.cpp b/src/boost/libs/thread/test/test_3628.cpp new file mode 100644 index 000000000..02914d810 --- /dev/null +++ b/src/boost/libs/thread/test/test_3628.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2010 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 2 + +#include <boost/thread/thread.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <list> +#include <iostream> + +#if defined BOOST_THREAD_USES_CHRONO + +using namespace std; + +boost::recursive_mutex theMutex; + +typedef std::list<boost::condition*> Conditions; +Conditions theConditions; + +void ThreadFuncWaiter() +{ + boost::condition con1; + //for(; ; ) + for (int j = 0; j < 10; j++) + { + { + boost::unique_lock<boost::recursive_mutex> lockMtx(theMutex); + theConditions.push_back(&con1); + + cout << "Added " << boost::this_thread::get_id() << " " << &con1 << endl; + if (con1.timed_wait(lockMtx, boost::posix_time::time_duration(0, 0, 50))) + { + cout << "Woke Up " << boost::this_thread::get_id() << " " << &con1 << endl; + } + else + { + cout << "*****Timed Out " << boost::this_thread::get_id() << " " << &con1 << endl; + exit(13); + } + + theConditions.remove(&con1); + cout << "Removed " << boost::this_thread::get_id() << " " << &con1 << endl; + cout << "Waiter " << j << endl; + + } + //Sleep(2000); + boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); + } +} + +void ThreadFuncNotifier() +{ + for (int j = 0; j < 70; j++) + { + { + boost::unique_lock<boost::recursive_mutex> lockMtx(theMutex); + cout << "<Notifier " << j << endl; + + unsigned int i = 0; + for (Conditions::iterator it = theConditions.begin(); it != theConditions.end() && i < 2; ++it) + { + (*it)->notify_one(); + //WORKAROUND_ lockMtx.unlock(); + //WORKAROUND_ boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); + cout << "Notified One " << theConditions.size() << " " << (*it) << endl; + ++i; + //WORKAROUND_ lockMtx.lock(); + } + + cout << "Notifier> " << j << endl; + } + boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); + } +} + +int main() +{ + boost::thread_group tg; + for (int i = 0; i < 12; ++i) + { + tg.create_thread(ThreadFuncWaiter); + } + + tg.create_thread(ThreadFuncNotifier); + + tg.join_all(); + + return 0; +} + + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/test_3837.cpp b/src/boost/libs/thread/test/test_3837.cpp new file mode 100644 index 000000000..fd0056f33 --- /dev/null +++ b/src/boost/libs/thread/test/test_3837.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2010 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 <iostream> +#include <boost/thread.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/optional.hpp> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost; +using namespace boost::chrono; + +struct dummy_class_tracks_deletions +{ + static unsigned deletions; + + dummy_class_tracks_deletions() + { + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + } + ~dummy_class_tracks_deletions() + { + ++deletions; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + } + +}; +unsigned dummy_class_tracks_deletions::deletions=0; + + +optional<thread_specific_ptr<dummy_class_tracks_deletions> > optr; +//struct X +//{ +// thread_specific_ptr<int> f; +//} sptr; + +void other_thread() +{ + + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = none; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = in_place(); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == 0); + this_thread::sleep(posix_time::seconds(5)); + BOOST_TEST(optr->get() == 0); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + +} + +int main() +{ + + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + dummy_class_tracks_deletions * pi = new dummy_class_tracks_deletions; + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr = in_place(); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + optr->reset(pi); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == pi); + thread t1(bind(&other_thread)); + this_thread::sleep(posix_time::seconds(5)); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + BOOST_TEST(optr->get() == pi); + std::cout << __FILE__ << ":" << __LINE__ << boost::this_thread::get_id() << std::endl; + t1.join(); + return boost::report_errors(); + +} diff --git a/src/boost/libs/thread/test/test_4521.cpp b/src/boost/libs/thread/test/test_4521.cpp new file mode 100644 index 000000000..2b1a21bf2 --- /dev/null +++ b/src/boost/libs/thread/test/test_4521.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2010 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 2 + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/future.hpp> + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + +int main() { +boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything); + +//boost::unique_future<int> fi = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); +boost::unique_future<int> fi((BOOST_THREAD_MAKE_RV_REF(pt.get_future()))); + +boost::thread task(boost::move(pt)); // launch task on a thread + +fi.wait(); // wait for it to finish + +//assert(fi.is_ready()); +//assert(fi.has_value()); +//assert(!fi.has_exception()); +//assert(fi.get_state()==boost::future_state::ready); +//assert(fi.get()==42); +} diff --git a/src/boost/libs/thread/test/test_4648.cpp b/src/boost/libs/thread/test/test_4648.cpp new file mode 100644 index 000000000..34fb131af --- /dev/null +++ b/src/boost/libs/thread/test/test_4648.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2010 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 <iostream> +#include <boost/thread.hpp> +#include <boost/current_function.hpp> + +class boostThreadLocksTest +{ +public: + boost::shared_mutex myMutex; + //boost::upgrade_lock<boost::shared_mutex> myLock; + static int firstFunction(boostThreadLocksTest *pBoostThreadLocksTest); + static int secondFunction(boostThreadLocksTest *pBoostThreadLocksTest, + boost::upgrade_lock<boost::shared_mutex>& upgr); + boostThreadLocksTest() + :myMutex() + //, myLock(myMutex,boost::defer_lock_t()) + {} +}; + +int boostThreadLocksTest::firstFunction(boostThreadLocksTest *pBoostThreadLocksTest) +{ + std::cout<<"Entering "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + boost::upgrade_lock<boost::shared_mutex> myLock(pBoostThreadLocksTest->myMutex); + pBoostThreadLocksTest->secondFunction(pBoostThreadLocksTest, myLock); + std::cout<<"Returned From Call "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + std::cout<<"Returning from "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl; + return(0); +} +int boostThreadLocksTest::secondFunction(boostThreadLocksTest *, boost::upgrade_lock<boost::shared_mutex>& upgr) { + std::cout<<"Before Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl; + boost::upgrade_to_unique_lock<boost::shared_mutex> localUniqueLock(upgr); + std::cout<<"After Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl; + return(0); +} +int main() { + boostThreadLocksTest myObject; + boost::thread_group myThreadGroup; + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.create_thread(boost::bind(boostThreadLocksTest::firstFunction,&myObject)); + myThreadGroup.join_all(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_4882.cpp b/src/boost/libs/thread/test/test_4882.cpp new file mode 100644 index 000000000..b1bb72539 --- /dev/null +++ b/src/boost/libs/thread/test/test_4882.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2010 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 2 +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +//#define BOOST_THREAD_USES_LOG + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/detail/no_exceptions_support.hpp> +//#include <boost/thread/detail/log.hpp> + +boost::shared_mutex mutex; + +void thread() +{ + //BOOST_THREAD_LOG << "<thrd" << BOOST_THREAD_END_LOG; + BOOST_TRY + { + for (int i =0; i<10; ++i) + { +#ifndef BOOST_THREAD_USES_CHRONO + boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(50); + + if (mutex.timed_lock(timeout)) + { + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + mutex.unlock(); + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + } +#else + boost::chrono::system_clock::time_point timeout = boost::chrono::system_clock::now() + boost::chrono::milliseconds(50); + + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + if (mutex.try_lock_until(timeout)) + { + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); + mutex.unlock(); + //BOOST_THREAD_LOG << "<thrd" << " i="<<i << BOOST_THREAD_END_LOG; + } +#endif + } + } + BOOST_CATCH (boost::lock_error& ) + { + //BOOST_THREAD_LOG << "lock_error exception thrd>" << BOOST_THREAD_END_LOG; + } + BOOST_CATCH (...) + { + //BOOST_THREAD_LOG << "exception thrd>" << BOOST_THREAD_END_LOG; + } + BOOST_CATCH_END + //BOOST_THREAD_LOG << "thrd>" << BOOST_THREAD_END_LOG; +} + +int main() +{ + //BOOST_THREAD_LOG << "<main" << BOOST_THREAD_END_LOG; + const int nrThreads = 20; + boost::thread* threads[nrThreads]; + + for (int i = 0; i < nrThreads; ++i) + threads[i] = new boost::thread(&thread); + + for (int i = 0; i < nrThreads; ++i) + { + threads[i]->join(); + //BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + delete threads[i]; + //BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + } + //BOOST_THREAD_LOG << "main>" << BOOST_THREAD_END_LOG; + return 0; +} diff --git a/src/boost/libs/thread/test/test_5351.cpp b/src/boost/libs/thread/test/test_5351.cpp new file mode 100644 index 000000000..958afb31d --- /dev/null +++ b/src/boost/libs/thread/test/test_5351.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2010 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_PROVIDES_INTERRUPTIONS + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/thread/future.hpp> + +using namespace boost::posix_time; +using namespace boost; + +int foo() +{ + this_thread::sleep(seconds(10)); + return 0; +} + + +int main() +{ + boost::packaged_task<int> pt(&foo); + boost::unique_future<int> fi = pt.get_future(); + boost::thread task(boost::move(pt)); // launch task on a thread + + task.interrupt(); + + try + { + int v = fi.get(); + } + catch (boost::thread_interrupted& exc) + { + std::cout << "OK: " << std::endl; + return 0; + } + catch (boost::exception& exc) + { + std::cout << __LINE__ << " ERROR: " << boost::diagnostic_information(exc) << std::endl; + return 1; + } + catch (...) + { + std::cout << __LINE__ << " ERROR: " << std::endl; + return 2; + } + std::cout << __LINE__ << " ERROR: " << std::endl; + return 3; +} diff --git a/src/boost/libs/thread/test/test_5502.cpp b/src/boost/libs/thread/test/test_5502.cpp new file mode 100644 index 000000000..455e79eec --- /dev/null +++ b/src/boost/libs/thread/test/test_5502.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2010 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) + +// bm.cpp + +// g++ test.cpp -lboost_thread-mt && ./a.out + +// the ration of XXX and YYY determines +// if this works or deadlocks +int XXX = 20; +int YYY = 10; + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> + +//#include <unistd.h> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +using namespace std; + +//void sleepmillis(useconds_t miliis) +void sleepmillis(int miliis) +{ + //usleep(miliis * 1000); + boost::this_thread::sleep(boost::posix_time::milliseconds(miliis)); +} + +void worker1(boost::shared_mutex * lk, int * x) +{ + (*x)++; // 1 + cout << "lock b try " << *x << endl; + while (1) + { + if (lk->timed_lock(boost::posix_time::milliseconds(XXX))) break; + sleepmillis(YYY); + } + cout << "lock b got " << *x << endl; + (*x)++; // 2 + lk->unlock(); +} + +void worker2(boost::shared_mutex * lk, int * x) +{ + cout << "lock c try" << endl; + lk->lock_shared(); + (*x)++; + cout << "lock c got" << endl; + lk->unlock_shared(); + cout << "lock c unlocked" << endl; + (*x)++; +} + +int main() +{ + + // create + boost::shared_mutex* lk = new boost::shared_mutex(); + + // read lock + cout << "lock a" << endl; + lk->lock_shared(); + + int x1 = 0; + boost::thread t1(boost::bind(worker1, lk, &x1)); + while (!x1) + ; + BOOST_TEST(x1 == 1); + sleepmillis(500); + BOOST_TEST(x1 == 1); + + int x2 = 0; + boost::thread t2(boost::bind(worker2, lk, &x2)); + t2.join(); + BOOST_TEST(x2 == 2); + + lk->unlock_shared(); + cout << "unlock a" << endl; + + for (int i = 0; i < 2000; i++) + { + if (x1 == 2) break; + sleepmillis(10); + } + + BOOST_TEST(x1 == 2); + t1.join(); + delete lk; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5542_1.cpp b/src/boost/libs/thread/test/test_5542_1.cpp new file mode 100644 index 000000000..4d088dc80 --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_1.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2010 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 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +class Worker +{ +public: + + Worker() + { + // the thread is not-a-thread until we call start() + } + + void start(int N) + { +// std::cout << "start\n"; + m_Thread = boost::thread(&Worker::processQueue, this, N); +// std::cout << "started\n"; + } + + void join() + { + m_Thread.join(); + } + + void processQueue(unsigned N) + { + unsigned ms = N * 1000; + boost::posix_time::milliseconds workTime(ms); + +// std::cout << "Worker: started, will work for " +// << ms << "ms" +// << std::endl; + + // We're busy, honest! + boost::this_thread::sleep(workTime); + +// std::cout << "Worker: completed" << std::endl; + } + +private: + + boost::thread m_Thread; +}; + +int main() +{ +// std::cout << "main: startup" << std::endl; + + Worker worker; + +// std::cout << "main: create worker" << std::endl; + + worker.start(3); + +// std::cout << "main: waiting for thread" << std::endl; + + worker.join(); + +// std::cout << "main: done" << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5542_2.cpp b/src/boost/libs/thread/test/test_5542_2.cpp new file mode 100644 index 000000000..b0c48cf9d --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_2.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2010 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 2 + +#include <boost/thread/thread_only.hpp> + +void run_thread() { + return; +} + +int main() { + boost::thread t(&run_thread); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_5542_3.cpp b/src/boost/libs/thread/test/test_5542_3.cpp new file mode 100644 index 000000000..4541243f3 --- /dev/null +++ b/src/boost/libs/thread/test/test_5542_3.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2010 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 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/date_time.hpp> + +void workerFunc() +{ + boost::posix_time::seconds workTime(3); + + std::cout << "Worker: running" << std::endl; + + // Pretend to do something useful... + boost::this_thread::sleep(workTime); + + std::cout << "Worker: finished" << std::endl; +} + +int main() +{ + std::cout << "main: startup" << std::endl; + + boost::thread workerThread(workerFunc); + + std::cout << "main: waiting for thread" << std::endl; + + workerThread.join(); + + std::cout << "main: done" << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_5891.cpp b/src/boost/libs/thread/test/test_5891.cpp new file mode 100644 index 000000000..bb1af3d57 --- /dev/null +++ b/src/boost/libs/thread/test/test_5891.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2010 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 2 + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +using namespace std; +using namespace boost; + + struct X { + void operator()() + { + boost::this_thread::sleep(posix_time::seconds(2)); + } + }; +int main() +{ + X run; + boost::thread myThread(run); + boost::this_thread::yield(); + if(myThread.timed_join(posix_time::seconds(5))) + { + cout << "thats ok"; + return 0; + } + else + { + cout << "too late"; + return 1; + } +} diff --git a/src/boost/libs/thread/test/test_6130.cpp b/src/boost/libs/thread/test/test_6130.cpp new file mode 100644 index 000000000..a351039bf --- /dev/null +++ b/src/boost/libs/thread/test/test_6130.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2010 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 2 + +#include <boost/thread/thread_only.hpp> +#include <boost/date_time/posix_time/posix_time_io.hpp> +#include <assert.h> +#include <iostream> +#include <stdlib.h> +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <unistd.h> +#endif + +boost::mutex mtx; +boost::condition_variable cv; + +using namespace boost::posix_time; +using namespace boost::gregorian; +int main() +{ +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) + + for (int i=0; i<3; ++i) + { + const time_t now_time = ::time(0); + const time_t wait_time = now_time+1; + time_t end_time; + assert(now_time < wait_time); + + boost::unique_lock<boost::mutex> lk(mtx); + //const bool res = + (void)cv.timed_wait(lk, from_time_t(wait_time)); + end_time = ::time(0); + std::cerr << "now_time =" << now_time << " \n"; + std::cerr << "end_time =" << end_time << " \n"; + std::cerr << "wait_time=" << wait_time << " \n"; + std::cerr << "now_time =" << from_time_t(now_time) << " \n"; + std::cerr << "end_time =" << from_time_t(end_time) << " \n"; + std::cerr << "wait_time=" << from_time_t(wait_time) << " \n"; + std::cerr << end_time - wait_time << " \n"; + assert(end_time >= wait_time); + std::cerr << " OK\n"; + } +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_6170.cpp b/src/boost/libs/thread/test/test_6170.cpp new file mode 100644 index 000000000..5ddb21e61 --- /dev/null +++ b/src/boost/libs/thread/test/test_6170.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2010 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 <boost/thread/shared_mutex.hpp> +#include <boost/thread/locks.hpp> + +// Including this will cause ambiguous errors in boost::move +#include <boost/unordered_map.hpp> + +using namespace boost; + +typedef upgrade_lock<shared_mutex> auto_upgrade_lock; +typedef upgrade_to_unique_lock<shared_mutex> auto_upgrade_unique_lock; + +void testUpgrade(void) +{ + shared_mutex mtx; + auto_upgrade_lock lock(mtx); + // Do some read-only stuff + + auto_upgrade_unique_lock writeLock(lock); + // Do some write-only stuff with the upgraded lock +} + +int main() +{ + testUpgrade(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_6174.cpp b/src/boost/libs/thread/test/test_6174.cpp new file mode 100644 index 000000000..bc28dcfad --- /dev/null +++ b/src/boost/libs/thread/test/test_6174.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2010 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 <boost/thread/thread_only.hpp> +#include <boost/thread/future.hpp> +#include <boost/config.hpp> + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +struct MovableButNonCopyable { +#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS + MovableButNonCopyable(MovableButNonCopyable const&) = delete; + MovableButNonCopyable& operator=(MovableButNonCopyable const&) = delete; +#else +private: + MovableButNonCopyable(MovableButNonCopyable const&); + MovableButNonCopyable& operator=(MovableButNonCopyable const&); +#endif +public: + MovableButNonCopyable() {}; + MovableButNonCopyable(MovableButNonCopyable&&) {}; + MovableButNonCopyable& operator=(MovableButNonCopyable&&) + { + return *this; + }; +}; + +MovableButNonCopyable construct() +{ + return MovableButNonCopyable(); +} + +int main() +{ + boost::packaged_task<MovableButNonCopyable> pt(construct); + pt(); + return 0; +} +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/test_7160.cpp b/src/boost/libs/thread/test/test_7160.cpp new file mode 100644 index 000000000..644d87fa8 --- /dev/null +++ b/src/boost/libs/thread/test/test_7160.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2010 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_DATE_TIME_POSIX_TIME_STD_CONFIG + +#include <iostream> +#include <boost/thread/thread_only.hpp> + +class ThreadClass +{ +public: + ThreadClass() + { + } + + void operator()() + { + return; + } +}; + +int main() +{ + boost::posix_time::ptime currentTimeUTC; + + ThreadClass tc; + boost::thread t(tc); + t.join(); //causes a runtime access violation here + + std::cout << "done" << std::endl; + //system("pause"); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_7328.cpp b/src/boost/libs/thread/test/test_7328.cpp new file mode 100644 index 000000000..0c0cca03a --- /dev/null +++ b/src/boost/libs/thread/test/test_7328.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2010 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_PROVIDES_INTERRUPTIONS + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +//using namespace boost; +using namespace boost::chrono; + +bool interrupted = false; +void f() +{ + try + { + std::cout << "Starting sleep in thread" << std::endl; + for (;;) + { + boost::this_thread::sleep_for(seconds(60)); + } + } + catch (const boost::thread_interrupted&) + { + interrupted = true; + std::cout << "Thread interrupted." << std::endl; + } +} + +int main() +{ + boost::thread t(f); + t.interrupt(); + t.join(); + std::cout << "Joined with thread." << std::endl; + BOOST_TEST(interrupted); + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/test_7571.cpp b/src/boost/libs/thread/test/test_7571.cpp new file mode 100644 index 000000000..a336795f4 --- /dev/null +++ b/src/boost/libs/thread/test/test_7571.cpp @@ -0,0 +1,93 @@ +// 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 2 + +#include <boost/date_time.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <iostream> + +// Number should be big enough to allow context switch between threads, otherwise the bug doesn't show. +static int MAX_COUNTS; + +class ItemKeeper { + +public: + ItemKeeper() { } + + void doSomething() { + boost::unique_lock<boost::mutex> scoped_lock(mutex); + int counts = MAX_COUNTS; + while (counts--); + } + +private: + boost::mutex mutex; +}; + +ItemKeeper itemKeeper; + +int MAX_ITERATIONS(5); + +void threadFunc(int invokerID, bool& exceptionOccurred) { + try { + for (int i = 0; i < MAX_ITERATIONS; i++) { + std::cout << "Thread " << invokerID << ", iteration " << i << std::endl; + itemKeeper.doSomething(); + } + } catch (...) { + exceptionOccurred = true; + } +} + + +int main(int argc, char* argv[]) { + if (argc < 2) { + MAX_COUNTS = 5000000; + } else { + std::string valueStr(argv[1]); + bool has_only_digits = (valueStr.find_first_not_of( "0123456789" ) == std::string::npos); + if (has_only_digits) { + std::istringstream aStream(valueStr); + aStream >> MAX_COUNTS; + } else { + std::cerr << "Argument should be an integer\n"; + return 1; + } + } + + bool exceptionOccurred1(false); + bool exceptionOccurred2(false); + + boost::thread thread1(threadFunc, 1, boost::ref(exceptionOccurred1)); + boost::thread thread2(threadFunc, 2, boost::ref(exceptionOccurred2)); + + boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(10000*100); + + bool deadlockOccured(false); + //thread1.join(); + //thread2.join(); + + if (!thread1.timed_join(timeout)) { + deadlockOccured = true; + thread1.interrupt(); + } + if (!thread2.timed_join(timeout)) { + deadlockOccured = true; + thread2.interrupt(); + } + + if (deadlockOccured) { + std::cout << "Deadlock occurred\n"; + return 1; + } + if (exceptionOccurred1 || exceptionOccurred2) { + std::cout << "Exception occurred\n"; + return 1; + } + return 0; +} + diff --git a/src/boost/libs/thread/test/test_7665.cpp b/src/boost/libs/thread/test/test_7665.cpp new file mode 100644 index 000000000..7244a7d34 --- /dev/null +++ b/src/boost/libs/thread/test/test_7665.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2010 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 2 +#define BOOST_THREAD_USES_LOG + +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/detail/log.hpp> + +void thread() +{ + BOOST_THREAD_LOG << "<thrd" << BOOST_THREAD_END_LOG; + try { + boost::this_thread::sleep_for(boost::chrono::seconds(30)); + } catch (...) + { + BOOST_THREAD_LOG << "thrd exception" << BOOST_THREAD_END_LOG; + throw; + } + //while (1) ; // Never quit + BOOST_THREAD_LOG << "thrd>" << BOOST_THREAD_END_LOG; +} + +boost::thread example(thread); + +int main() +{ + BOOST_THREAD_LOG << "<main" << BOOST_THREAD_END_LOG; + boost::this_thread::sleep_for(boost::chrono::seconds(30)); + BOOST_THREAD_LOG << "main" << BOOST_THREAD_END_LOG; + //while (1) ; // Never quit + example.join(); + BOOST_THREAD_LOG << "main>" << BOOST_THREAD_END_LOG; + return 0; +} + diff --git a/src/boost/libs/thread/test/test_7666.cpp b/src/boost/libs/thread/test/test_7666.cpp new file mode 100644 index 000000000..1ec71dff8 --- /dev/null +++ b/src/boost/libs/thread/test/test_7666.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2010 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_CHRONO_VERSION 2 +#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread_only.hpp> + +void myFunc() +{ + boost::this_thread::sleep(boost::posix_time::seconds(5)); +} + +int main(int, char **) +{ + boost::thread p(myFunc); + + p.join(); + + return 0; +} diff --git a/src/boost/libs/thread/test/test_7720.cpp b/src/boost/libs/thread/test/test_7720.cpp new file mode 100644 index 000000000..4dfe95a73 --- /dev/null +++ b/src/boost/libs/thread/test/test_7720.cpp @@ -0,0 +1,56 @@ +// 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) + +//////////////////////////////////////////// + +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +using namespace boost; + +shared_mutex mtx; + +const int max_count = 100; +void f() +{ + int count =max_count; + while (count--) + { + upgrade_lock<shared_mutex> lock(mtx); + } +} + +void g() +{ + int count =max_count; + while (count--) + { + shared_lock<shared_mutex> lock(mtx); + } +} + +void h() +{ + int count =max_count; + while (count--) + { + unique_lock<shared_mutex> lock(mtx); + } +} + +int main() +{ + thread t0(f); + thread t1(g); + thread t2(h); + + t0.join(); + t1.join(); + t2.join(); + + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_7755.cpp b/src/boost/libs/thread/test/test_7755.cpp new file mode 100644 index 000000000..5551a6bb9 --- /dev/null +++ b/src/boost/libs/thread/test/test_7755.cpp @@ -0,0 +1,94 @@ +// 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) + +//////////////////////////////////////////// + +//#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#include <iostream> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/shared_mutex.hpp> +// shared_mutex_deadlock.cpp : Defines the entry point for the console application. +// + + +boost::shared_mutex mutex; + +void thread2_func() +{ + int i (0); + for (;;) + { + if (mutex.timed_lock(boost::posix_time::milliseconds(500))) + { + std::cout << "Unique lock acquired" << std::endl + << "Test successful" << std::endl; + mutex.unlock(); + break; + } + ++i; + if (i == 100) + { + std::cout << "Test failed. App is deadlocked" << std::endl; + break; + } + boost::this_thread::sleep(boost::posix_time::seconds(1)); + } +} + +void thread3_func() +{ + boost::shared_lock<boost::shared_mutex> lock (mutex); + std::cout << "Shared lock acquired" << std::endl + << "Test successful" << std::endl; +} + +void thread3_func_workaround() +{ + for (;;) + { + if (mutex.timed_lock_shared(boost::posix_time::milliseconds(200))) + { + std::cout << "Shared lock acquired" << std::endl + << "Test successful" << std::endl; + mutex.unlock_shared(); + break; + } + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } +} + +int main() +{ + std::cout << "Starting" << std::endl; + + // 1 - lock the mutex + boost::shared_lock<boost::shared_mutex> lock (mutex); + + // 2 - start thread#2 + boost::thread thread2(&thread2_func); + + // 3 - sleep + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + std::cout << "Thread#2 is waiting" << std::endl; + + // - start thread3 + boost::thread thread3(&thread3_func); + //boost::thread thread3(&thread3_func_workaround); + + std::cout << "Thread#3 is started and blocked. It never will waked" << std::endl; + + thread3.join(); // will never return + + lock.unlock(); // release shared ownership. thread#2 will take unique ownership + + thread2.join(); + + std::cout << "Finished" << std::endl; + return 0; +} + + + diff --git a/src/boost/libs/thread/test/test_8455.cpp b/src/boost/libs/thread/test/test_8455.cpp new file mode 100644 index 000000000..bbc4e5673 --- /dev/null +++ b/src/boost/libs/thread/test/test_8455.cpp @@ -0,0 +1,23 @@ +// 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 <boost/thread/mutex.hpp> +boost::mutex mut; +void boostMutexImp1() +{ + boost::mutex::scoped_lock lock(mut); + mut.unlock(); // A: with this X blocks + //lock.unlock(); // No influence if used also if before A +} +void boostMutexImp2() +{ + boost::mutex::scoped_lock lock(mut); // X: blocks with A +} +int main() +{ + boostMutexImp1(); + boostMutexImp2(); + return 0; +} diff --git a/src/boost/libs/thread/test/test_8508.cpp b/src/boost/libs/thread/test/test_8508.cpp new file mode 100644 index 000000000..f53d1487d --- /dev/null +++ b/src/boost/libs/thread/test/test_8508.cpp @@ -0,0 +1,20 @@ +// 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) + +//#define BOOST_THREAD_VERSION 2 + +#include <boost/thread/thread.hpp> + +void thread_main() +{ +} + +int main(void) +{ + boost::thread t(thread_main); + t.join(); + return 0; +} + diff --git a/src/boost/libs/thread/test/test_8557.cpp b/src/boost/libs/thread/test/test_8557.cpp new file mode 100644 index 000000000..b8efee5a1 --- /dev/null +++ b/src/boost/libs/thread/test/test_8557.cpp @@ -0,0 +1,140 @@ +// 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) + +// B + +#include <malloc.h> +#include <boost/thread/thread.hpp> + +#include <boost/thread/mutex.hpp> + +#include <boost/bind/bind.hpp> + +#include <iostream> + + static void + display_mallinfo() + { + struct mallinfo mi; + + mi = mallinfo(); + + printf("Total non-mmapped bytes (arena): %d\n", mi.arena); + printf("# of free chunks (ordblks): %d\n", mi.ordblks); + printf("# of free fastbin blocks (smblks): %d\n", mi.smblks); + printf("# of mapped regions (hblks): %d\n", mi.hblks); + printf("Bytes in mapped regions (hblkhd): %d\n", mi.hblkhd); + printf("Max. total allocated space (usmblks): %d\n", mi.usmblks); + printf("Free bytes held in fastbins (fsmblks): %d\n", mi.fsmblks); + printf("Total allocated space (uordblks): %d\n", mi.uordblks); + printf("Total free space (fordblks): %d\n", mi.fordblks); + printf("Topmost releasable block (keepcost): %d\n", mi.keepcost); + } + +boost::mutex io_mutex; + +void count() { + + for (int i = 0; i < 10; ++i) { + + boost::mutex::scoped_lock lock(io_mutex); + + //boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) ); + + } + +} +void* count2(void*) { + + for (int i = 0; i < 10; ++i) { + + boost::mutex::scoped_lock lock(io_mutex); + + boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) ); + + } + return 0; +} + +int main() { + printf("\n============== sizeof(boost::thread) ============== %d\n", sizeof(boost::thread)); + printf("\n============== sizeof(boost::detail::thread_data_base) ============== %d\n", sizeof(boost::detail::thread_data_base)); + printf("\n============== sizeof(boost::detail::thread_data<>) ============== %d\n", sizeof(boost::detail::thread_data<void(*)()>)); + printf("\n============== Before thread creation ==============\n"); + display_mallinfo(); + { + boost::thread thrd1(&count); + + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + boost::thread thrd2(&count); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + boost::thread thrd3(&count); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + thrd1.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + thrd2.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + thrd3.join(); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + } + printf("\n============== After thread destruction ==============\n"); + display_mallinfo(); + + { + pthread_attr_t attr; + pthread_attr_init(&attr); + + pthread_t thrd1; + pthread_create(&thrd1, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_t thrd2; + pthread_create(&thrd2, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_t thrd3; + pthread_create(&thrd3, &attr, &count2, 0); + printf("\n============== After thread creation ==============\n"); + display_mallinfo(); + + pthread_attr_destroy(&attr); + printf("\n============== After thread attr destroy ==============\n"); + display_mallinfo(); + + void* res; + pthread_join(thrd3, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + pthread_join(thrd2, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + pthread_join(thrd1, &res); + printf("\n============== After thread join ==============\n"); + display_mallinfo(); + + + + //pthread_destroy(&thrd1); + //pthread_destroy(&thrd2); + //pthread_destroy(&thrd3); + } + printf("\n============== After thread destruction ==============\n"); + display_mallinfo(); + + return 1; + +} diff --git a/src/boost/libs/thread/test/test_8586.cpp b/src/boost/libs/thread/test/test_8586.cpp new file mode 100644 index 000000000..926f8b398 --- /dev/null +++ b/src/boost/libs/thread/test/test_8586.cpp @@ -0,0 +1,18 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +void hello_world() +{ + std::cout << "Hello from thread!" << std::endl; +} + +int main() +{ + boost::thread my_thread(&hello_world); + my_thread.join(); +} diff --git a/src/boost/libs/thread/test/test_8596.cpp b/src/boost/libs/thread/test/test_8596.cpp new file mode 100644 index 000000000..d8af66e87 --- /dev/null +++ b/src/boost/libs/thread/test/test_8596.cpp @@ -0,0 +1,61 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> +#include <functional> +//#include <future> + +#include <boost/thread.hpp> +#include <boost/shared_ptr.hpp> + +int f() +{ + return 42; +} + +boost::packaged_task<int()>* schedule(boost::function<int ()> const& fn) +{ + // Normally, the pointer to the packaged task is stored in a queue + // for execution on a separate thread, and the schedule function + // would return just a future<T> + + boost::function<int ()> copy(fn); + boost::packaged_task<int()>* result = new boost::packaged_task<int()>(copy); + return result; +} + +struct MyFunc +{ + MyFunc(MyFunc const&) = delete; + MyFunc& operator=(MyFunc const&) = delete; + MyFunc() {}; + MyFunc(MyFunc &&) {}; + MyFunc& operator=(MyFunc &&) { return *this;}; + void operator()()const {} +}; + + +int main() +{ + boost::packaged_task<int()>* p(schedule(f)); + (*p)(); + + boost::future<int> fut = p->get_future(); + std::cout << "The answer to the ultimate question: " << fut.get() << std::endl; + + { + boost::function<void()> f; + MyFunc mf; + + boost::packaged_task<void()> t1(f); + boost::packaged_task<void()> t2(boost::move(mf)); + } + + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_8600.cpp b/src/boost/libs/thread/test/test_8600.cpp new file mode 100644 index 000000000..224e41fa6 --- /dev/null +++ b/src/boost/libs/thread/test/test_8600.cpp @@ -0,0 +1,140 @@ +// 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 <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <vector> +#include <utility> +#include <type_traits> +#if 1 + +struct B { + int v; + B(int i) : v(i) {} +}; + +struct D: B { + D(int i) : B(i) {} +}; + +void fb(B const&) {} +void fd(D const&) {} + +BOOST_STATIC_ASSERT(sizeof(B)==sizeof(D)); + +template <class T, class Allocator=std::allocator<T> > +class new_vector; +template <class T, class Allocator> +class new_vector : public std::vector<T,Allocator> +{ + typedef std::vector<T,Allocator> base_type; +public: + new_vector() : base_type() {} + new_vector(unsigned s) : base_type(s) {} +}; + +template <class Allocator > +class new_vector<bool, Allocator> +{ + //std::vector<char,typename Allocator::template rebind<char>::other > v; + int i; +public: +}; + +template <class T, class A> +typename std::enable_if<!std::is_same<T, bool>::value, + new_vector<T,A>& +>::type +new_vector_cast(std::vector<T,A> & v) { + return reinterpret_cast<new_vector<T,A>&>(v); +} + +BOOST_STATIC_ASSERT(sizeof(std::vector<int>)==sizeof(new_vector<int>)); +BOOST_STATIC_ASSERT(sizeof(std::vector<bool>)!=sizeof(new_vector<bool>)); + +void fb(std::vector<int> const&) {} +void fd(new_vector<int> const&) {} + +int main() { + { + std::vector<int> b(1); + b[0] = 1; + new_vector<int> d = new_vector_cast(b); + BOOST_ASSERT(b[0] == d[0]); + } + { + //std::vector<bool> b; + //new_vector<bool> d = new_vector_cast(b); // compile fail + } + { + std::vector<int> b(1); + b[0] = 1; + fd(new_vector_cast(b)); + } + { + new_vector<int> d(1); + d[0] = 1; + std::vector<int> b = d; + BOOST_ASSERT(b[0] == d[0]); + } + { + //new_vector<bool> d; + //std::vector<bool> b = d; // compile fail + } + { + new_vector<int> d(1); + d[0] = 1; + fd(d); + } + return 0; +} + + +#else +int main() { + { + B b(1); + D d = reinterpret_cast<D&>(b); + BOOST_ASSERT(b.v == d.v); + } + { + B b(1); + fd(reinterpret_cast<D&>(b)); + } + { + D d(2); + B b = d; + BOOST_ASSERT(b.v == d.v); + } + { + D d(2); + fd(d); + } + return 0; +} + +#define BOOST_THREAD_VERSION 4 + +#include <iostream> +#include <boost/thread.hpp> + +int calculate_the_answer_to_life_the_universe_and_everything() +{ +return 42; +} + +int main() +{ +boost::packaged_task<int()> pt(calculate_the_answer_to_life_the_universe_and_everything); +boost::shared_future<int> fi1 = boost::shared_future<int>(pt.get_future()); +boost::shared_future<int> fi2 = fi1; + +boost::thread task(boost::move(pt)); // launch task on a thread + +boost::wait_for_any(fi1, fi2); +std::cout << "Wait for any returned\n"; +return (0); +} +#endif diff --git a/src/boost/libs/thread/test/test_8674.cpp b/src/boost/libs/thread/test/test_8674.cpp new file mode 100644 index 000000000..87a6524d8 --- /dev/null +++ b/src/boost/libs/thread/test/test_8674.cpp @@ -0,0 +1,43 @@ +// 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 <iostream> + +#define USE_STD 0 +#define USE_BOOST 1 + +#define USED_THREAD_API USE_BOOST +//#define USED_THREAD_API USE_STD + +#if USED_THREAD_API == USE_BOOST + +# define BOOST_THREAD_VERSION 4 +# include <boost/thread/future.hpp> + + using boost::future; + using boost::async; + +#endif +#if USED_THREAD_API == USE_STD +# include <future> + using std::future; + using std::async; +#endif + + + +future<void> do_something() +{ + auto result = async( []{ std::cout<< "A\n"; } ); + std::cout << "B\n"; + return result; // error here +} + +int main() +{ + do_something().wait(); + std::cout << "Hello, World!" << std::endl; + return 0; +} diff --git a/src/boost/libs/thread/test/test_8943.cpp b/src/boost/libs/thread/test/test_8943.cpp new file mode 100644 index 000000000..99cf70de1 --- /dev/null +++ b/src/boost/libs/thread/test/test_8943.cpp @@ -0,0 +1,47 @@ +// 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 <boost/detail/lightweight_test.hpp> + +#if defined(WIN32) +#include <tchar.h> +#endif + +#include <cstdlib> +#include <iostream> +#include <boost/thread/once.hpp> + +namespace { + +class foo +{ +public: + void operator()() const + { + std::cout << "foo" << std::endl; + } +}; // class foo + +} + +#if defined(WIN32) +int _tmain(int /*argc*/, _TCHAR* /*argv*/[]) +#else +int main(int /*argc*/, char* /*argv*/[]) +#endif +{ + try + { + boost::once_flag once_flag = BOOST_ONCE_INIT; + boost::call_once(once_flag, foo()); + return EXIT_SUCCESS; + } + catch (...) + { + std::cerr << "Unknown exception" << std::endl; + BOOST_TEST(false); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_8960.cpp b/src/boost/libs/thread/test/test_8960.cpp new file mode 100644 index 000000000..84cce77e4 --- /dev/null +++ b/src/boost/libs/thread/test/test_8960.cpp @@ -0,0 +1,53 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +#include <iostream> + +#include <boost/thread.hpp> +#include <boost/thread/locks.hpp> +#include <boost/chrono.hpp> +//#include <boost/bind/bind.hpp> +#include <boost/detail/lightweight_test.hpp> + + +void do_thread() +{ + + try + { + boost::condition_variable c1; + boost::mutex m1; + boost::unique_lock<boost::mutex> l1(m1); + + c1.wait_for(l1, boost::chrono::seconds(1)); + } + catch (std::runtime_error& ex) + { + std::cout << "EXCEPTION ! " << ex.what() << std::endl; + BOOST_TEST(false); + + } + catch (...) + { + std::cout << "EXCEPTION ! " << std::endl; + BOOST_TEST(false); + } + +} + +int main() +{ + + boost::thread th1(&do_thread); + th1.join(); + + //std::string s1; + //std::cin >> s1; + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_9079_a.cpp b/src/boost/libs/thread/test/test_9079_a.cpp new file mode 100644 index 000000000..3e8ca03fd --- /dev/null +++ b/src/boost/libs/thread/test/test_9079_a.cpp @@ -0,0 +1,57 @@ +// 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) + +// A + +//#include <boost/log/trivial.hpp> +#include <boost/chrono.hpp> +#include <boost/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +//#if !defined(BOOST_NO_CXX11_ALIGNAS) +//#error +//# define BOOST_ALIGNMENT2(x) alignas(x) +//#elif defined(_MSC_VER) +//#error +//# define BOOST_ALIGNMENT2(x) __declspec(align(x)) +//#elif defined(__GNUC__) +//#error +//# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x))) +//#else +//#error +//# define BOOST_NO_ALIGNMENT2 +//# define BOOST_ALIGNMENT2(x) +//#endif + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point TimePoint; + +inline TimePoint real_time_now() +{ + return Clock::now(); +} + +int main() +{ + using namespace boost::chrono; + + boost::condition_variable m_task_spawn_condition; + + boost::mutex main_thread_mutex; + boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex); + + //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN"; + + //for (;;) + { + static const milliseconds TIME_BACK = milliseconds(1); + m_task_spawn_condition.wait_until( + main_thread_lock, + real_time_now() - TIME_BACK); // wait forever + m_task_spawn_condition.wait_for( main_thread_lock, - TIME_BACK ); // same problem + //BOOST_LOG_TRIVIAL(trace) << "TICK"; + } + +} diff --git a/src/boost/libs/thread/test/test_9079_b.cpp b/src/boost/libs/thread/test/test_9079_b.cpp new file mode 100644 index 000000000..90abd206f --- /dev/null +++ b/src/boost/libs/thread/test/test_9079_b.cpp @@ -0,0 +1,86 @@ +// 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) + +// B + +#include <boost/atomic.hpp> +//#include <boost/log/trivial.hpp> +#include <boost/chrono.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/thread.hpp> +#include <boost/thread/condition_variable.hpp> + +typedef boost::chrono::high_resolution_clock Clock; +typedef Clock::time_point TimePoint; + +inline TimePoint real_time_now() +{ + return Clock::now(); +} + +class Foo { + boost::atomic<bool> m_is_exiting; + TimePoint m_next_tick_time; + +public: + + bool is_exiting() const + { + return m_is_exiting; + } + + TimePoint spawn_tasks() // note that in my app, this call takes more time than here + { + using namespace boost::chrono; + const TimePoint now = real_time_now(); + + if (m_next_tick_time < now) { + m_next_tick_time = now + seconds(1); + //BOOST_LOG_TRIVIAL(info) << "TICK!"; + } + + return m_next_tick_time; + } + +}; + +int main() +{ + using namespace boost::chrono; + static const milliseconds MIN_TIME_TASKS_SPAWN_FREQUENCY = milliseconds(1); + //microseconds(1); // THE SHORTER THE QUICKER TO REPRODUCE THE BUG + + boost::condition_variable m_task_spawn_condition; + Foo foo; + + boost::mutex main_thread_mutex; + boost::unique_lock < boost::mutex > main_thread_lock(main_thread_mutex); + + //BOOST_LOG_TRIVIAL(info) << "[TaskScheduler::run_and_wait] Scheduling loop - BEGIN"; + + int i =11; + while (i--) + { + const TimePoint next_task_spawn_time = foo.spawn_tasks(); + + const TimePoint now = real_time_now(); + const TimePoint next_minimum_spawn_time = now + MIN_TIME_TASKS_SPAWN_FREQUENCY; + const TimePoint next_spawn_time = next_task_spawn_time > TimePoint() + && next_task_spawn_time < next_minimum_spawn_time + ? next_task_spawn_time : next_minimum_spawn_time; + + const TimePoint::duration wait_time = next_spawn_time - now; + if (wait_time > wait_time.zero()) { + // BOOST_LOG_TRIVIAL(trace) << "WAIT TIME: " << wait_time; // UNCOMMENT THIS: MAKES IT WORKS. WAT?????? + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + std::cout << next_spawn_time << std::endl; + m_task_spawn_condition.wait_until( + main_thread_lock, + next_spawn_time); // DON'T WORK: WILL WAIT IF next_spawn_time is too close! + } + + } + +} diff --git a/src/boost/libs/thread/test/test_9192.cpp b/src/boost/libs/thread/test/test_9192.cpp new file mode 100644 index 000000000..c7aad7dd8 --- /dev/null +++ b/src/boost/libs/thread/test/test_9192.cpp @@ -0,0 +1,145 @@ +// 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 <boost/interprocess/shared_memory_object.hpp> +#include <boost/interprocess/mapped_region.hpp> +#include <boost/thread.hpp> + +using namespace boost::interprocess; + +struct item +{ + int i; +}; + +struct queue +{ + void put( const item& item ) + { + boost::unique_lock<boost::mutex> lock(mutex); + while ( item_in ) + cond_full.wait(lock); + + item_ = item; + item_in = true; + cond_empty.notify_one(); + } + + void print() + { + boost::unique_lock<boost::mutex> lock(mutex); + while ( !item_in ) + cond_empty.wait(lock); + + item_in = false; + std::cout << item_.i << std::endl; + cond_full.notify_one(); + } + + +private: + //Mutex to protect access to the queue + boost::mutex mutex; + + //Condition to wait when the queue is empty + boost::condition_variable cond_empty; + + //Condition to wait when the queue is full + boost::condition_variable cond_full; + + bool item_in; + + //Items to fill + item item_; +}; + +void *addr; + +void printThread() +{ + //Erase previous shared memory and schedule erasure on exit + struct shm_remove + { + shm_remove() { shared_memory_object::remove("MySharedMemory"); } + ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } + } remover; + + //Create a shared memory object. + shared_memory_object shm(create_only,"MySharedMemory",read_write); + + try + { +// //Set size +// shm.truncate(sizeof(queue)); +// +// //Map the whole shared memory in this process +// mapped_region region(shm,read_write); +// +// //Get the address of the mapped region +// void *addr = region.get_address(); + + //Construct the shared structure in memory + queue *q = new (addr) queue; + + do + { + q->print(); + } while ( true ); + } +// catch(interprocess_exception &ex) +// { +// std::cout << ex.what() << std::endl; +// } + catch(boost::thread_interrupted&) + { + std::cout << "interrupted" << std::endl; + } + catch(...) + { + std::cout << "exception" << std::endl; + } +} + +int main() +{ + addr = new queue(); + boost::thread t(printThread); + + // give the thread time to create the shm + boost::this_thread::sleep( boost::posix_time::milliseconds( 1000 ) ); + +// //Create a shared memory object. +// shared_memory_object shm(open_only,"MySharedMemory",read_write); + + try + { +// //Map the whole shared memory in this process +// mapped_region region(shm,read_write); +// +// //Get the address of the mapped region +// void *addr = region.get_address(); + + //Obtain a pointer to the shared structure + queue *q = static_cast<queue*>(addr); + + item i; + i.i = 42; + q->put( i ); + + ++i.i; + q->put( i ); + + // give the printThread time to "process" the item + boost::this_thread::sleep( boost::posix_time::milliseconds( 1000 ) ); + + t.interrupt(); + t.join(); + } + catch(...) + { + std::cout << "exception" << std::endl; + return -1; + } +} diff --git a/src/boost/libs/thread/test/test_9303.cpp b/src/boost/libs/thread/test/test_9303.cpp new file mode 100644 index 000000000..af8be567d --- /dev/null +++ b/src/boost/libs/thread/test/test_9303.cpp @@ -0,0 +1,177 @@ +// 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) + +#define BOOST_THREAD_VERSION 4 + #include <iostream> + #include <fstream> + #include <stdio.h> + #include <boost/function.hpp> + #include <boost/make_shared.hpp> + #include <boost/shared_ptr.hpp> + #include <boost/bind/bind.hpp> + #include <boost/asio.hpp> + #include <boost/thread.hpp> + #include <boost/thread/future.hpp> + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + #define EXAMPLE_1 + #define EXAMPLE_2 + #define EXAMPLE_3 + #define EXAMPLE_4 + #define EXAMPLE_5 + #define EXAMPLE_6 + #define EXAMPLE_7 +#else + #define EXAMPLE_1 + #define EXAMPLE_2 + //#define EXAMPLE_3 + //#define EXAMPLE_4 + //#define EXAMPLE_5 + //#define EXAMPLE_6 + //#define EXAMPLE_7 +#endif + + // Test functions + + int int_no_params() + { + return 42; + } + + int int_with_params(int i) + { + return i; + } + + std::string string_no_params() + { + return std::string("forty two"); + } + + std::string string_with_params(std::string& ans) + { + return ans; + } + + int main(int /*argc*/, char ** /*argv[]*/) + { + std::string ans("forty two"); + + #if defined EXAMPLE_1 + //! Compiles and produces correct result. + { + boost::packaged_task<int()> example(int_no_params); + boost::future<int> f = example.get_future(); + boost::thread task(boost::move(example)); + int answer = f.get(); + std::cout << "Answer to life and whatnot, in English: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_2 + //! Compiles and produces correct result. + { + boost::packaged_task<std::string()> example(string_no_params); + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example)); + std::string answer = f.get(); + std::cout << "string_no_params: " << answer << std::endl; + task.join(); + } + + #endif + + #if defined EXAMPLE_3 + //! Doesn't compile in C++03. + //! error: variable âboost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> exampleâ has initializer but incomplete type + + { + boost::packaged_task<std::string(std::string&)> example(string_with_params); + boost::future<std::string> f = example.get_future(); + example(ans); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + } + + #endif + + #if defined EXAMPLE_4 + //! Doesn't compile in C++11 +// In file included from test_9303.cpp:10: +// In file included from ../../../boost/thread.hpp:13: +// In file included from ../../../boost/thread/thread.hpp:12: +// In file included from ../../../boost/thread/thread_only.hpp:22: +// ../../../boost/thread/detail/thread.hpp:76:15: error: no matching function for call to 'invoke' +// invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); +// ^~~~~~ + + { + boost::packaged_task<std::string(std::string&)> example(string_with_params); + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example), boost::ref(ans)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_5 + //! Doesn't compile in C++03, C++11 only. + //! error: extended initializer lists only available with -std=c++11 or -std=gnu++11 [-Werror] + { + boost::packaged_task<std::string(std::string&)> example + { boost::bind(&string_with_params, ans) }; + boost::future<std::string> f = example.get_future(); + boost::thread task(boost::move(example), boost::ref(ans)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_6 + //! Doesn't compile in C++03, C++11 only. + // packagedTestTest.cpp:94:43: error: invalid use of incomplete type ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + // packagedTestTest.cpp:95:37: error: incomplete type ‘task_t {aka boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>}’ used in nested name specifier + // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + { + //typedef boost::packaged_task<std::string(std::string&)> task_t; + typedef boost::packaged_task<std::string()> task_t; + boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, boost::ref(ans))); + boost::future<std::string> f = example->get_future(); + boost::thread task(boost::bind(&task_t::operator(), example)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + task.join(); + } + #endif + + #if defined EXAMPLE_7 + //! Doesn't compile in C++03, C++11 only. + // packagedTestTest.cpp:94:43: error: invalid use of incomplete type ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + // packagedTestTest.cpp:95:37: error: incomplete type ‘task_t {aka boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>}’ used in nested name specifier + // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ + { + boost::asio::io_service io_service; + boost::thread_group threads; + boost::asio::io_service::work work(io_service); + + for (int i = 0; i < 3; ++i) + { + threads.create_thread(boost::bind(&boost::asio::io_service::run, + &io_service)); + } + typedef boost::packaged_task<std::string()> task_t; + boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, ans)); + boost::future<std::string> f = example->get_future(); + io_service.post(boost::bind(&task_t::operator(), example)); + std::string answer = f.get(); + std::cout << "string_with_params: " << answer << std::endl; + threads.join_all(); + } + #endif + return 0; + } diff --git a/src/boost/libs/thread/test/test_9319.cpp b/src/boost/libs/thread/test/test_9319.cpp new file mode 100644 index 000000000..5dafe4d49 --- /dev/null +++ b/src/boost/libs/thread/test/test_9319.cpp @@ -0,0 +1,60 @@ +// 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) + +// futtest.cpp +#include <iostream> +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/future.hpp> +#include <boost/thread/thread.hpp> +#include <boost/bind/bind.hpp> +#include <boost/chrono.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_ptr.hpp> + +typedef boost::shared_ptr< boost::promise<int> > IntPromise; + +void foo(IntPromise p) +{ + std::cout << "foo" << std::endl; + p->set_value(123); // This line locks the future's mutex, then calls the continuation with the mutex already locked. +} + +void bar(boost::future<int> fooResult) +{ + try { + std::cout << "bar" << std::endl; + int i = fooResult.get(); // Code hangs on this line (Due to future already being locked by the set_value call) + std::cout << "i: " << i << std::endl; + } catch(...) { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + } +} + +int main() +{ + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + try { + IntPromise p(new boost::promise<int>()); + boost::thread t(boost::bind(foo, p)); + boost::future<int> f1 = p->get_future(); + f1.then(boost::launch::deferred, &bar); + t.join(); + } catch(...) { + return 1; + } + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + try { + IntPromise p(new boost::promise<int>()); + boost::thread t(boost::bind(foo, p)); + boost::future<int> f1 = p->get_future(); + f1.then(boost::launch::async, &bar); + t.join(); + } catch(...) { + return 2; + } + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +} + diff --git a/src/boost/libs/thread/test/test_9711.cpp b/src/boost/libs/thread/test/test_9711.cpp new file mode 100644 index 000000000..d8fd8e3e8 --- /dev/null +++ b/src/boost/libs/thread/test/test_9711.cpp @@ -0,0 +1,44 @@ +// 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) + +#define BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +#include <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include <boost/thread/future.hpp> + + +int main() +{ +#if ! defined BOOST_NO_CXX11_LAMBDAS && ! (defined BOOST_MSVC && _MSC_VER < 1700) + boost::promise<int> prom; + boost::future<int> futr = prom.get_future(); + + int callCount = 0; + + boost::future<void> futr2 = futr.then(boost::launch::deferred, + [&] (boost::future<int> f) { + callCount++; + assert(f.valid()); + assert(f.is_ready()); + assert(17 == f.get()); + }); + + assert(futr2.valid()); + assert(!futr2.is_ready()); + assert(0 == callCount); + + prom.set_value(17); + assert(0 == callCount); + + futr2.get(); + assert(1 == callCount); + +#endif + return 0; +} diff --git a/src/boost/libs/thread/test/test_9856.cpp b/src/boost/libs/thread/test/test_9856.cpp new file mode 100644 index 000000000..b7dcc6e37 --- /dev/null +++ b/src/boost/libs/thread/test/test_9856.cpp @@ -0,0 +1,29 @@ +#include "boost/atomic.hpp" +#include "boost/thread.hpp" +#include <iostream> + +using namespace boost; + +int main() { + atomic<size_t> total(0), failures(0); + +#pragma omp parallel shared(total, failures) num_threads(1000) + { + mutex mtx; + condition_variable cond; + unique_lock<mutex> lk(mtx); + for (int i = 0; i < 500; i++) { + ++total; + if (cv_status::timeout != cond.wait_for(lk, chrono::milliseconds(10))) + ++failures; + } + } + if(failures) + std::cout << "There were " << failures << " failures out of " << total << " timed waits." << std::endl; + if((100*failures)/total>40) + { + std::cerr << "This exceeds 10%, so failing the test." << std::endl; + return 1; + } + return 0; +} diff --git a/src/boost/libs/thread/test/test_barrier.cpp b/src/boost/libs/thread/test/test_barrier.cpp new file mode 100644 index 000000000..5baf19cd4 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// (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) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + +// Shared variables for generation barrier test +const int N_THREADS=3; +boost::barrier gen_barrier(N_THREADS); +boost::mutex mutex; +long global_parameter; + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + if (gen_barrier.wait()) + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_barrier_size_fct.cpp b/src/boost/libs/thread/test/test_barrier_size_fct.cpp new file mode 100644 index 000000000..2671af848 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier_size_fct.cpp @@ -0,0 +1,69 @@ +// (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) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + + +// Shared variables for generation barrier test +long global_parameter; +const int N_THREADS=3; + +unsigned int size_fct() { + global_parameter++; + return N_THREADS; +} + +boost::barrier gen_barrier(N_THREADS, &size_fct); + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + gen_barrier.count_down_and_wait(); + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_barrier_void_fct.cpp b/src/boost/libs/thread/test/test_barrier_void_fct.cpp new file mode 100644 index 000000000..77a65e581 --- /dev/null +++ b/src/boost/libs/thread/test/test_barrier_void_fct.cpp @@ -0,0 +1,68 @@ +// (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) + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/barrier.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace { + + +// Shared variables for generation barrier test +long global_parameter; + +void void_fct() { + global_parameter++; +} + +const int N_THREADS=3; +boost::barrier gen_barrier(N_THREADS, &void_fct); + +void barrier_thread() +{ + for (int i = 0; i < 5; ++i) + { + gen_barrier.count_down_and_wait(); + } +} + +} // namespace + +void test_barrier() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&barrier_thread); + g.join_all(); + } + catch(...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + + BOOST_TEST(global_parameter==5); + +} + +int main() +{ + + test_barrier(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_completion_latch.cpp b/src/boost/libs/thread/test/test_completion_latch.cpp new file mode 100644 index 000000000..bef883654 --- /dev/null +++ b/src/boost/libs/thread/test/test_completion_latch.cpp @@ -0,0 +1,108 @@ +// 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) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/completion_latch.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace +{ + + // Shared variables for generation completion_latch test + const int N_THREADS = 10; + boost::completion_latch gen_latch(N_THREADS); + boost::mutex mutex; + long global_parameter; + + void latch_thread() + { + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + gen_latch.count_down(); + //do something else + } + +} // namespace + +void test_global_parameter() +{ + boost::unique_lock<boost::mutex> lock(mutex); + BOOST_TEST_EQ(global_parameter, N_THREADS); +} + +void reset_gen_latch() +{ + { + boost::unique_lock<boost::mutex> lock(mutex); + BOOST_TEST_EQ(global_parameter, N_THREADS); + } + gen_latch.reset(N_THREADS); +} + +void test_completion_latch_reset() +{ + boost::thread_group g; + boost::thread_group g2; + + gen_latch.then(&reset_gen_latch); + + { + global_parameter = 0; + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&latch_thread); + + if (!gen_latch.try_wait()) + if (gen_latch.wait_for(boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + if (gen_latch.wait_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + gen_latch.wait(); // All the threads have been updated the global_parameter + g.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + } + gen_latch.then(&test_global_parameter); + { + global_parameter = 0; + try + { + for (int i = 0; i < N_THREADS; ++i) + g2.create_thread(&latch_thread); + + if (!gen_latch.try_wait()) + gen_latch.wait(); // All the threads have been updated the global_parameter + + g2.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g2.interrupt_all(); + g2.join_all(); + //throw; + } + } +} + +int main() +{ + test_completion_latch_reset(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_condition.cpp b/src/boost/libs/thread/test/test_condition.cpp new file mode 100644 index 000000000..210860b71 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: condition test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> + +#include <boost/config.hpp> +#include <boost/test/unit_test.hpp> + +#include "./util.inl" + +struct condition_test_data +{ + condition_test_data() : notified(0), awoken(0) { } + + boost::mutex mutex; + boost::condition_variable condition; + int notified; + int awoken; +}; + +void condition_test_thread(condition_test_data* data) +{ + boost::unique_lock<boost::mutex> lock(data->mutex); + BOOST_CHECK(lock ? true : false); + while (!(data->notified > 0)) + data->condition.wait(lock); + BOOST_CHECK(lock ? true : false); + data->awoken++; +} + +struct cond_predicate +{ + cond_predicate(int& var, int val) : _var(var), _val(val) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + cond_predicate(cond_predicate const&) = default; +#endif + + bool operator()() { return _var == _val; } + + int& _var; + int _val; + +private: + void operator=(cond_predicate&); +}; + +void condition_test_waits(condition_test_data* data) +{ + boost::unique_lock<boost::mutex> lock(data->mutex); + BOOST_CHECK(lock ? true : false); + + // Test wait. + while (data->notified != 1) + data->condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 1); + data->awoken++; + data->condition.notify_one(); + + // Test predicate wait. + data->condition.wait(lock, cond_predicate(data->notified, 2)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 2); + data->awoken++; + data->condition.notify_one(); + + // Test timed_wait. + boost::xtime xt = delay(10); + while (data->notified != 3) + data->condition.timed_wait(lock, xt); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data->notified, 3); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait. + xt = delay(10); + cond_predicate pred(data->notified, 4); + BOOST_CHECK(data->condition.timed_wait(lock, xt, pred)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK(pred()); + BOOST_CHECK_EQUAL(data->notified, 4); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait with relative timeout + cond_predicate pred_rel(data->notified, 5); + BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel)); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK(pred_rel()); + BOOST_CHECK_EQUAL(data->notified, 5); + data->awoken++; + data->condition.notify_one(); +} + +void do_test_condition_waits() +{ + condition_test_data data; + + boost::thread thread(bind(&condition_test_waits, &data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + BOOST_CHECK(lock ? true : false); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 1) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 1); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 2) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 2); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 3) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 3); + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 4) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 4); + + + boost::thread::sleep(delay(1)); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 5) + data.condition.wait(lock); + BOOST_CHECK(lock ? true : false); + BOOST_CHECK_EQUAL(data.awoken, 5); + } + + thread.join(); + BOOST_CHECK_EQUAL(data.awoken, 5); +} + +BOOST_AUTO_TEST_CASE(test_condition_waits) +{ + // We should have already tested notify_one here, so + // a timed test with the default execution_monitor::use_condition + // should be OK, and gives the fastest performance + timed_test(&do_test_condition_waits, 12); +} + +void do_test_condition_wait_is_a_interruption_point() +{ + condition_test_data data; + + boost::thread thread(bind(&condition_test_thread, &data)); + + thread.interrupt(); + thread.join(); + BOOST_CHECK_EQUAL(data.awoken,0); +} + + +BOOST_AUTO_TEST_CASE(test_condition_wait_is_a_interruption_point) +{ + timed_test(&do_test_condition_wait_is_a_interruption_point, 1); +} + diff --git a/src/boost/libs/thread/test/test_condition_notify_all.cpp b/src/boost/libs/thread/test/test_condition_notify_all.cpp new file mode 100644 index 000000000..17c84d5d5 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_notify_all.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_all test suite +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" +#include "./condition_test_common.hpp" + +unsigned const number_of_test_threads=5; + +void do_test_condition_notify_all_wakes_from_wait() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::wait_without_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_timed_wait() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::timed_wait_without_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::timed_wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread_group group; + + try + { + for(unsigned i=0;i<number_of_test_threads;++i) + { + group.create_thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data)); + } + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_all(); + } + + group.join_all(); + BOOST_CHECK_EQUAL(data.woken,number_of_test_threads); + } + catch(...) + { + group.join_all(); + throw; + } +} + +namespace +{ + boost::mutex multiple_wake_mutex; + boost::condition_variable multiple_wake_cond; + unsigned multiple_wake_count=0; + + void wait_for_condvar_and_increase_count() + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + multiple_wake_cond.wait(lk); + ++multiple_wake_count; + } + +} + + +void do_test_notify_all_following_notify_one_wakes_all_threads() +{ + boost::thread thread1(&wait_for_condvar_and_increase_count); + boost::thread thread2(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + + boost::thread thread3(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + multiple_wake_cond.notify_all(); + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + BOOST_CHECK(multiple_wake_count==3); + } + + thread1.join(); + thread2.join(); + thread3.join(); +} + +BOOST_AUTO_TEST_CASE(test_condition_notify_all) +{ + timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds); + timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds); + timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds); +} + + + diff --git a/src/boost/libs/thread/test/test_condition_notify_one.cpp b/src/boost/libs/thread/test/test_condition_notify_one.cpp new file mode 100644 index 000000000..00aff6268 --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_notify_one.cpp @@ -0,0 +1,148 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: condition_variable notify_one test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" +#include "./condition_test_common.hpp" + +void do_test_condition_notify_one_wakes_from_wait() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::wait_without_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_timed_wait() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::timed_wait_without_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::timed_wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate() +{ + wait_for_flag data; + + boost::thread thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data)); + + { + boost::unique_lock<boost::mutex> lock(data.mutex); + data.flag=true; + data.cond_var.notify_one(); + } + + thread.join(); + BOOST_CHECK(data.woken); +} + +namespace +{ + boost::mutex multiple_wake_mutex; + boost::condition_variable multiple_wake_cond; + unsigned multiple_wake_count=0; + + void wait_for_condvar_and_increase_count() + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + multiple_wake_cond.wait(lk); + ++multiple_wake_count; + } + +} + + +void do_test_multiple_notify_one_calls_wakes_multiple_threads() +{ + boost::thread thread1(&wait_for_condvar_and_increase_count); + boost::thread thread2(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + + boost::thread thread3(&wait_for_condvar_and_increase_count); + + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + multiple_wake_cond.notify_one(); + multiple_wake_cond.notify_one(); + boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + + { + boost::unique_lock<boost::mutex> lk(multiple_wake_mutex); + BOOST_CHECK(multiple_wake_count==3); + } + + thread1.join(); + thread2.join(); + thread3.join(); +} + +BOOST_AUTO_TEST_CASE(test_condition_notify_one) +{ + timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex); + timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex); +} diff --git a/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp b/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp new file mode 100644 index 000000000..8e19cd7bf --- /dev/null +++ b/src/boost/libs/thread/test/test_condition_timed_wait_times_out.cpp @@ -0,0 +1,169 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: condition_variable test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/condition.hpp> +#include <boost/thread/thread_only.hpp> + +#include <boost/test/unit_test.hpp> +#include "./util.inl" + +bool fake_predicate() +{ + return false; +} + +unsigned const timeout_seconds=2; +unsigned const timeout_grace=1; +boost::posix_time::milliseconds const timeout_resolution(100); + + +void do_test_timed_wait_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + while(cond.timed_wait(lock,timeout)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_timed_wait_with_predicate_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + bool const res=cond.timed_wait(lock,timeout,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_relative_timed_wait_with_predicate_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + bool const res=cond.timed_wait(lock,delay,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_timed_wait_relative_times_out() +{ + boost::condition_variable cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + while(cond.timed_wait(lock,delay)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + while(cond.timed_wait(lock,timeout)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_with_predicate_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+delay; + + bool const res=cond.timed_wait(lock,timeout,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_relative_timed_wait_with_predicate_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + bool const res=cond.timed_wait(lock,delay,fake_predicate); + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK(!res); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + +void do_test_cv_any_timed_wait_relative_times_out() +{ + boost::condition_variable_any cond; + boost::mutex m; + + boost::posix_time::seconds const delay(timeout_seconds); + boost::unique_lock<boost::mutex> lock(m); + boost::system_time const start=boost::get_system_time(); + + while(cond.timed_wait(lock,delay)) {} + + boost::system_time const end=boost::get_system_time(); + BOOST_CHECK((delay-timeout_resolution)<=(end-start)); +} + + +BOOST_AUTO_TEST_CASE(test_timed_wait_times_out) +{ + timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); + timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex); +} + + diff --git a/src/boost/libs/thread/test/test_futures.cpp b/src/boost/libs/thread/test/test_futures.cpp new file mode 100644 index 000000000..61515169d --- /dev/null +++ b/src/boost/libs/thread/test/test_futures.cpp @@ -0,0 +1,1236 @@ +// (C) Copyright 2008-10 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: futures test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/future.hpp> +#include <utility> +#include <memory> +#include <string> +#include <iostream> +#include <boost/thread/detail/log.hpp> + +#include <boost/test/unit_test.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable: 4267) // conversion from ... to ..., possible loss of data +#endif + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename T> + typename boost::remove_reference<T>::type&& cast_to_rval(T&& t) + { + return static_cast<typename boost::remove_reference<T>::type&&>(t); + } +#else +#if defined BOOST_THREAD_USES_MOVE + template<typename T> + boost::rv<T>& cast_to_rval(T& t) + { + return boost::move(t); + } +#else + template<typename T> + boost::detail::thread_move_t<T> cast_to_rval(T& t) + { + return boost::move(t); + } +#endif +#endif + +struct X +{ +public: + int i; + + BOOST_THREAD_MOVABLE_ONLY(X) + X(): + i(42) + {} + X(BOOST_THREAD_RV_REF(X) other): + i(BOOST_THREAD_RV(other).i) + { + BOOST_THREAD_RV(other).i=0; + } + X& operator=(BOOST_THREAD_RV_REF(X) other) + { + i=BOOST_THREAD_RV(other).i; + BOOST_THREAD_RV(other).i=0; + return *this; + } + ~X() + {} +}; +namespace boost { + BOOST_THREAD_DCL_MOVABLE(X) +} + +int make_int() +{ + return 42; +} + +int throw_runtime_error() +{ + throw std::runtime_error("42"); +} + +void set_promise_thread(boost::promise<int>* p) +{ + p->set_value(42); +} + +struct my_exception +{}; + +void set_promise_exception_thread(boost::promise<int>* p) +{ + p->set_exception(boost::copy_exception(my_exception())); +} + + +BOOST_AUTO_TEST_CASE(test_store_value_from_thread) +{ + BOOST_DETAIL_THREAD_LOG; + try { + boost::promise<int> pi2; + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi2.get_future())); + BOOST_DETAIL_THREAD_LOG; + boost::thread(set_promise_thread,&pi2); + BOOST_DETAIL_THREAD_LOG; + int j=fi2.get(); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(j==42); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.is_ready()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.has_value()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(!fi2.has_exception()); + BOOST_DETAIL_THREAD_LOG; + BOOST_CHECK(fi2.get_state()==boost::future_state::ready); + BOOST_DETAIL_THREAD_LOG; + } + catch (...) + { + BOOST_CHECK(false&&"Exception thrown"); + } +} + +BOOST_AUTO_TEST_CASE(test_store_exception) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi3; + boost::unique_future<int> fi3(BOOST_THREAD_MAKE_RV_REF(pi3.get_future())); + boost::thread(set_promise_exception_thread,&pi3); + try + { + fi3.get(); + BOOST_CHECK(false); + } + catch(my_exception) + { + BOOST_CHECK(true); + } + + BOOST_CHECK(fi3.is_ready()); + BOOST_CHECK(!fi3.has_value()); + BOOST_CHECK(fi3.has_exception()); + BOOST_CHECK(fi3.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_initial_state) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> fi; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + int i; + try + { + i=fi.get(); + (void)i; + BOOST_CHECK(false); + } + catch(boost::future_uninitialized) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_waiting_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + int i=0; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::waiting); + BOOST_CHECK(i==0); +} + +BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + try + { + pi.get_future(); + BOOST_CHECK(false); + } + catch(boost::future_already_retrieved&) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + pi.set_value(42); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi; + fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + + pi.set_value(42); + + int i=0; + BOOST_CHECK(i=fi.get()); + BOOST_CHECK(i==42); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved) +{ + BOOST_DETAIL_THREAD_LOG; +// boost::promise<int> pi; +// boost::unique_future<int> fi; +// fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); + +// pi.set_value(42); + +// int i=0; +// BOOST_CHECK(i=fi.get()); +// BOOST_CHECK(i==42); +// BOOST_CHECK(fi.is_ready()); +// BOOST_CHECK(fi.has_value()); +// BOOST_CHECK(!fi.has_exception()); +// BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + int i=0; + BOOST_CHECK(!fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::waiting); + BOOST_CHECK(i==0); +} + +BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + int i=0; + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + BOOST_CHECK(i=fi.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + + pt(); + try + { + pt(); + BOOST_CHECK(false); + } + catch(boost::task_already_started) + { + BOOST_CHECK(true); + } +} + + +BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + pt.get_future(); + try + { + pt.get_future(); + BOOST_CHECK(false); + } + catch(boost::future_already_retrieved) + { + BOOST_CHECK(true); + } +} + +BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(throw_runtime_error); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi.has_value()); + BOOST_CHECK(fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + try + { + fi.get(); + BOOST_CHECK(false); + } + catch(std::exception&) + { + BOOST_CHECK(true); + } + catch(...) + { + BOOST_CHECK(!"Unknown exception thrown"); + } + +} + +BOOST_AUTO_TEST_CASE(test_void_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<void> p; + boost::unique_future<void> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + p.set_value(); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + f.get(); +} + +BOOST_AUTO_TEST_CASE(test_reference_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int&> p; + boost::unique_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + int i=42; + p.set_value(i); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + BOOST_CHECK(&f.get()==&i); +} + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_task_returning_void) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<void> pt(do_nothing); + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); +} + +int global_ref_target=0; + +int& return_ref() +{ + return global_ref_target; +} + +BOOST_AUTO_TEST_CASE(test_task_returning_reference) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int&> pt(return_ref); + boost::unique_future<int&> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt(); + + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(fi.has_value()); + BOOST_CHECK(!fi.has_exception()); + BOOST_CHECK(fi.get_state()==boost::future_state::ready); + int& i=fi.get(); + BOOST_CHECK(&i==&global_ref_target); +} + +BOOST_AUTO_TEST_CASE(test_shared_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi=pt.get_future(); + + boost::shared_future<int> sf(::cast_to_rval(fi)); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + pt(); + + int i=0; + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<int> sf(::cast_to_rval(fi)); + boost::shared_future<int> sf2(sf); + boost::shared_future<int> sf3; + sf3=sf; + BOOST_CHECK(sf.get_state()==boost::future_state::waiting); + BOOST_CHECK(sf2.get_state()==boost::future_state::waiting); + BOOST_CHECK(sf3.get_state()==boost::future_state::waiting); + + pt(); + + int i=0; + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf.get()); + BOOST_CHECK(i==42); + i=0; + BOOST_CHECK(sf2.is_ready()); + BOOST_CHECK(sf2.has_value()); + BOOST_CHECK(!sf2.has_exception()); + BOOST_CHECK(sf2.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf2.get()); + BOOST_CHECK(i==42); + i=0; + BOOST_CHECK(sf3.is_ready()); + BOOST_CHECK(sf3.has_value()); + BOOST_CHECK(!sf3.has_exception()); + BOOST_CHECK(sf3.get_state()==boost::future_state::ready); + BOOST_CHECK(i=sf3.get()); + BOOST_CHECK(i==42); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<int> sf; + sf=::cast_to_rval(fi); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + BOOST_CHECK(!sf.is_ready()); + BOOST_CHECK(!sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::waiting); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_void) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<void> pt(do_nothing); + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + boost::shared_future<void> sf(::cast_to_rval(fi)); + BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); + + pt(); + + BOOST_CHECK(sf.is_ready()); + BOOST_CHECK(sf.has_value()); + BOOST_CHECK(!sf.has_exception()); + BOOST_CHECK(sf.get_state()==boost::future_state::ready); + sf.get(); +} + +BOOST_AUTO_TEST_CASE(test_shared_future_ref) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int&> p; + boost::shared_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); + int i=42; + p.set_value(i); + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_value()); + BOOST_CHECK(!f.has_exception()); + BOOST_CHECK(f.get_state()==boost::future_state::ready); + BOOST_CHECK(&f.get()==&i); +} + +BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + boost::promise<int> pi2(::cast_to_rval(pi)); + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + pi2.set_value(3); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi2.is_ready()); + BOOST_CHECK(fi.get()==3); + pi.set_value(42); + BOOST_CHECK(fi2.is_ready()); + BOOST_CHECK(fi2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<void> pi; + boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + boost::promise<void> pi2(::cast_to_rval(pi)); + boost::unique_future<void> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + + pi2.set_value(); + BOOST_CHECK(fi.is_ready()); + BOOST_CHECK(!fi2.is_ready()); + pi.set_value(); + BOOST_CHECK(fi2.is_ready()); +} + +BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<X> pt; + boost::unique_future<X> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt.set_value(X()); + X res(fi.get()); + BOOST_CHECK(res.i==42); +} + +BOOST_AUTO_TEST_CASE(test_unique_future_for_string) +{ + BOOST_DETAIL_THREAD_LOG; + boost::promise<std::string> pt; + boost::unique_future<std::string> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + pt.set_value(std::string("hello")); + std::string res(fi.get()); + BOOST_CHECK(res=="hello"); + + boost::promise<std::string> pt2; + fi=BOOST_THREAD_MAKE_RV_REF(pt2.get_future()); + + std::string const s="goodbye"; + + pt2.set_value(s); + res=fi.get(); + BOOST_CHECK(res=="goodbye"); + + boost::promise<std::string> pt3; + fi=BOOST_THREAD_MAKE_RV_REF(pt3.get_future()); + + std::string s2="foo"; + + pt3.set_value(s2); + res=fi.get(); + BOOST_CHECK(res=="foo"); +} + +boost::mutex callback_mutex; +unsigned callback_called=0; + +void wait_callback(boost::promise<int>& pi) +{ + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; + try + { + pi.set_value(42); + } + catch(...) + { + } +} + +void do_nothing_callback(boost::promise<int>& /*pi*/) +{ + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; +} + +BOOST_AUTO_TEST_CASE(test_wait_callback) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + pi.set_wait_callback(wait_callback); + fi.wait(); + BOOST_CHECK(callback_called); + BOOST_CHECK(fi.get()==42); + fi.wait(); + fi.wait(); + BOOST_CHECK(callback_called==1); +} + +BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::promise<int> pi; + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); + pi.set_wait_callback(do_nothing_callback); + bool success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(callback_called); + BOOST_CHECK(!success); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(!success); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(!success); + BOOST_CHECK(callback_called==3); + pi.set_value(42); + success=fi.timed_wait(boost::posix_time::milliseconds(10)); + BOOST_CHECK(success); + BOOST_CHECK(callback_called==3); + BOOST_CHECK(fi.get()==42); + BOOST_CHECK(callback_called==3); +} + + +void wait_callback_for_task(boost::packaged_task<int>& pt) +{ + BOOST_DETAIL_THREAD_LOG; + boost::lock_guard<boost::mutex> lk(callback_mutex); + ++callback_called; + try + { + pt(); + } + catch(...) + { + } +} + + +BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::packaged_task<int> pt(make_int); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + pt.set_wait_callback(wait_callback_for_task); + fi.wait(); + BOOST_CHECK(callback_called); + BOOST_CHECK(fi.get()==42); + fi.wait(); + fi.wait(); + BOOST_CHECK(callback_called==1); +} + +BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int); + + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + + BOOST_CHECK(!fi.is_ready()); + + boost::packaged_task<int> pt2(::cast_to_rval(pt)); + + BOOST_CHECK(!fi.is_ready()); + try + { + pt(); + BOOST_CHECK(!"Can invoke moved task!"); + } + catch(boost::task_moved&) + { + } + + BOOST_CHECK(!fi.is_ready()); + + pt2(); + + BOOST_CHECK(fi.is_ready()); +} + +BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> f; + + { + boost::promise<int> p; + f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_exception()); + try + { + f.get(); + } + catch(boost::broken_promise&) + { + } +} + +BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise) +{ + BOOST_DETAIL_THREAD_LOG; + boost::unique_future<int> f; + + { + boost::packaged_task<int> p(make_int); + f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + BOOST_CHECK(f.is_ready()); + BOOST_CHECK(f.has_exception()); + try + { + f.get(); + } + catch(boost::broken_promise&) + { + } +} + +int make_int_slowly() +{ + boost::this_thread::sleep(boost::posix_time::seconds(1)); + return 42; +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(f3.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f2.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f3.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + + boost::thread(::cast_to_rval(pt4)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4); + + BOOST_CHECK(future==3); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f4.is_ready()); + BOOST_CHECK(f4.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==0); + BOOST_CHECK(f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f1.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt2)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==1); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f2.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt3)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==2); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f3.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt4)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==3); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(f4.is_ready()); + BOOST_CHECK(!f5.is_ready()); + BOOST_CHECK(f4.get()==42); +} +BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5) +{ + BOOST_DETAIL_THREAD_LOG; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + boost::packaged_task<int> pt3(make_int_slowly); + boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); + boost::packaged_task<int> pt4(make_int_slowly); + boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); + boost::packaged_task<int> pt5(make_int_slowly); + boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); + + boost::thread(::cast_to_rval(pt5)); + + unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); + + BOOST_CHECK(future==4); + BOOST_CHECK(!f1.is_ready()); + BOOST_CHECK(!f2.is_ready()); + BOOST_CHECK(!f3.is_ready()); + BOOST_CHECK(!f4.is_ready()); + BOOST_CHECK(f5.is_ready()); + BOOST_CHECK(f5.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks) +{ + BOOST_DETAIL_THREAD_LOG; + callback_called=0; + boost::packaged_task<int> pt(make_int_slowly); + boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); + boost::packaged_task<int> pt2(make_int_slowly); + boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); + pt.set_wait_callback(wait_callback_for_task); + + boost::thread(::cast_to_rval(pt)); + + boost::wait_for_any(fi,fi2); + BOOST_CHECK(callback_called==1); + BOOST_CHECK(fi.get()==42); +} + +BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=10; + for(unsigned i=0;i<count;++i) + { + boost::packaged_task<int> tasks[count]; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + tasks[j]=boost::packaged_task<int>(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(tasks[j].get_future()); + } + boost::thread(::cast_to_rval(tasks[i])); + + BOOST_CHECK(boost::wait_for_any(futures,futures)==futures); + + boost::unique_future<int>* const future=boost::wait_for_any(futures,futures+count); + + BOOST_CHECK(future==(futures+i)); + for(unsigned j=0;j<count;++j) + { + if(j!=i) + { + BOOST_CHECK(!futures[j].is_ready()); + } + else + { + BOOST_CHECK(futures[j].is_ready()); + } + } + BOOST_CHECK(futures[i].get()==42); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=10; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures,futures+count); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=2; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=3; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=4; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2],futures[3]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} + +BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const count=5; + boost::unique_future<int> futures[count]; + for(unsigned j=0;j<count;++j) + { + boost::packaged_task<int> task(make_int_slowly); + futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); + boost::thread(::cast_to_rval(task)); + } + + boost::wait_for_all(futures[0],futures[1],futures[2],futures[3],futures[4]); + + for(unsigned j=0;j<count;++j) + { + BOOST_CHECK(futures[j].is_ready()); + } +} diff --git a/src/boost/libs/thread/test/test_generic_locks.cpp b/src/boost/libs/thread/test/test_generic_locks.cpp new file mode 100644 index 000000000..0a9befcf9 --- /dev/null +++ b/src/boost/libs/thread/test/test_generic_locks.cpp @@ -0,0 +1,578 @@ +// (C) Copyright 2008 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 + +#define BOOST_TEST_MODULE Boost.Threads: generic locks test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/condition_variable.hpp> +#include <iterator> +#include <cstddef> + +BOOST_AUTO_TEST_CASE(test_lock_two_uncontended) +{ + boost::mutex m1,m2; + + boost::unique_lock<boost::mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + + boost::lock(l1,l2); + + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); +} + +struct wait_data +{ + boost::mutex m; + bool flag; + boost::condition_variable cond; + + wait_data(): + flag(false) + {} + + void wait() + { + boost::unique_lock<boost::mutex> l(m); + while(!flag) + { + cond.wait(l); + } + } + + template<typename Duration> + bool timed_wait(Duration d) + { + boost::system_time const target=boost::get_system_time()+d; + + boost::unique_lock<boost::mutex> l(m); + while(!flag) + { + if(!cond.timed_wait(l,target)) + { + return flag; + } + } + return true; + } + + void signal() + { + boost::unique_lock<boost::mutex> l(m); + flag=true; + cond.notify_all(); + } +}; + + +void lock_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,wait_data* locked,wait_data* quit) +{ + boost::lock_guard<boost::mutex> l1(*m1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l2(*m2); + locked->signal(); + quit->wait(); +} + +void lock_pair(boost::mutex* m1,boost::mutex* m2) +{ + boost::lock(*m1,*m2); + boost::unique_lock<boost::mutex> l1(*m1,boost::adopt_lock), + l2(*m2,boost::adopt_lock); +} + +BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_order) +{ + boost::mutex m1,m2; + wait_data locked; + wait_data release; + + boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_pair,&m1,&m2); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_two_other_thread_locks_in_opposite_order) +{ + boost::mutex m1,m2; + wait_data locked; + wait_data release; + + boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_pair,&m2,&m1); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_uncontended) +{ + boost::mutex m1,m2,m3,m4,m5; + + boost::unique_lock<boost::mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock), + l3(m3,boost::defer_lock), + l4(m4,boost::defer_lock), + l5(m5,boost::defer_lock); + + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + BOOST_CHECK(!l5.owns_lock()); + + boost::lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + BOOST_CHECK(l5.owns_lock()); +} + +void lock_five_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5, + wait_data* locked,wait_data* quit) +{ + boost::lock_guard<boost::mutex> l1(*m1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l2(*m2); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l3(*m3); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l4(*m4); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + boost::lock_guard<boost::mutex> l5(*m5); + locked->signal(); + quit->wait(); +} + +void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5) +{ + boost::lock(*m1,*m2,*m3,*m4,*m5); + m1->unlock(); + m2->unlock(); + m3->unlock(); + m4->unlock(); + m5->unlock(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_order) +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_lock_five_other_thread_locks_in_different_order) +{ + boost::mutex m1,m2,m3,m4,m5; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +void lock_n(boost::mutex* mutexes,unsigned count) +{ + boost::lock(mutexes,mutexes+count); + for(unsigned i=0;i<count;++i) + { + mutexes[i].unlock(); + } +} + + +BOOST_AUTO_TEST_CASE(test_lock_ten_other_thread_locks_in_different_order) +{ + unsigned const num_mutexes=10; + + boost::mutex mutexes[num_mutexes]; + wait_data locked; + wait_data release; + + boost::thread t(lock_five_mutexes_slowly,&mutexes[6],&mutexes[3],&mutexes[8],&mutexes[0],&mutexes[2],&locked,&release); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + boost::thread t2(lock_n,mutexes,num_mutexes); + BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3))); + + release.signal(); + + BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3))); + + t.join(); +} + +struct dummy_mutex +{ + bool is_locked; + + dummy_mutex(): + is_locked(false) + {} + + void lock() + { + is_locked=true; + } + + bool try_lock() + { + if(is_locked) + { + return false; + } + is_locked=true; + return true; + } + + void unlock() + { + is_locked=false; + } +}; + +namespace boost +{ + template<> + struct is_mutex_type<dummy_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +} + + + +BOOST_AUTO_TEST_CASE(test_lock_five_in_range) +{ + unsigned const num_mutexes=5; + dummy_mutex mutexes[num_mutexes]; + + boost::lock(mutexes,mutexes+num_mutexes); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +class dummy_iterator +{ +private: + dummy_mutex* p; +public: + typedef std::forward_iterator_tag iterator_category; + typedef dummy_mutex value_type; + typedef std::ptrdiff_t difference_type; + typedef dummy_mutex* pointer; + typedef dummy_mutex& reference; + + explicit dummy_iterator(dummy_mutex* p_): + p(p_) + {} + + bool operator==(dummy_iterator const& other) const + { + return p==other.p; + } + + bool operator!=(dummy_iterator const& other) const + { + return p!=other.p; + } + + bool operator<(dummy_iterator const& other) const + { + return p<other.p; + } + + dummy_mutex& operator*() const + { + return *p; + } + + dummy_mutex* operator->() const + { + return p; + } + + dummy_iterator operator++(int) + { + dummy_iterator temp(*this); + ++p; + return temp; + } + + dummy_iterator& operator++() + { + ++p; + return *this; + } + +}; + + +BOOST_AUTO_TEST_CASE(test_lock_five_in_range_custom_iterator) +{ + unsigned const num_mutexes=5; + dummy_mutex mutexes[num_mutexes]; + + boost::lock(dummy_iterator(mutexes),dummy_iterator(mutexes+num_mutexes)); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +class dummy_mutex2: + public dummy_mutex +{}; + + +BOOST_AUTO_TEST_CASE(test_lock_ten_in_range_inherited_mutex) +{ + unsigned const num_mutexes=10; + dummy_mutex2 mutexes[num_mutexes]; + + boost::lock(mutexes,mutexes+num_mutexes); + + for(unsigned i=0;i<num_mutexes;++i) + { + BOOST_CHECK(mutexes[i].is_locked); + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_two_uncontended) +{ + dummy_mutex m1,m2; + + int const res=boost::try_lock(m1,m2); + + BOOST_CHECK(res==-1); + BOOST_CHECK(m1.is_locked); + BOOST_CHECK(m2.is_locked); +} +BOOST_AUTO_TEST_CASE(test_try_lock_two_first_locked) +{ + dummy_mutex m1,m2; + m1.lock(); + + boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==0); + BOOST_CHECK(m1.is_locked); + BOOST_CHECK(!m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} +BOOST_AUTO_TEST_CASE(test_try_lock_two_second_locked) +{ + dummy_mutex m1,m2; + m2.lock(); + + boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock), + l2(m2,boost::defer_lock); + + int const res=boost::try_lock(l1,l2); + + BOOST_CHECK(res==1); + BOOST_CHECK(!m1.is_locked); + BOOST_CHECK(m2.is_locked); + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); +} + +BOOST_AUTO_TEST_CASE(test_try_lock_three) +{ + int const num_mutexes=3; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + } + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_four) +{ + int const num_mutexes=4; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + } + } +} + +BOOST_AUTO_TEST_CASE(test_try_lock_five) +{ + int const num_mutexes=5; + + for(int i=-1;i<num_mutexes;++i) + { + dummy_mutex mutexes[num_mutexes]; + + if(i>=0) + { + mutexes[i].lock(); + } + boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock), + l2(mutexes[1],boost::defer_lock), + l3(mutexes[2],boost::defer_lock), + l4(mutexes[3],boost::defer_lock), + l5(mutexes[4],boost::defer_lock); + + int const res=boost::try_lock(l1,l2,l3,l4,l5); + + BOOST_CHECK(res==i); + for(int j=0;j<num_mutexes;++j) + { + if((i==j) || (i==-1)) + { + BOOST_CHECK(mutexes[j].is_locked); + } + else + { + BOOST_CHECK(!mutexes[j].is_locked); + } + } + if(i==-1) + { + BOOST_CHECK(l1.owns_lock()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l3.owns_lock()); + BOOST_CHECK(l4.owns_lock()); + BOOST_CHECK(l5.owns_lock()); + } + else + { + BOOST_CHECK(!l1.owns_lock()); + BOOST_CHECK(!l2.owns_lock()); + BOOST_CHECK(!l3.owns_lock()); + BOOST_CHECK(!l4.owns_lock()); + BOOST_CHECK(!l5.owns_lock()); + } + } +} + diff --git a/src/boost/libs/thread/test/test_hardware_concurrency.cpp b/src/boost/libs/thread/test/test_hardware_concurrency.cpp new file mode 100644 index 000000000..1d4376c27 --- /dev/null +++ b/src/boost/libs/thread/test/test_hardware_concurrency.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: hardware_concurrency test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> + +BOOST_AUTO_TEST_CASE(test_hardware_concurrency_is_non_zero) +{ + BOOST_CHECK(boost::thread::hardware_concurrency()!=0); +} + + diff --git a/src/boost/libs/thread/test/test_latch.cpp b/src/boost/libs/thread/test/test_latch.cpp new file mode 100644 index 000000000..e2972c9b1 --- /dev/null +++ b/src/boost/libs/thread/test/test_latch.cpp @@ -0,0 +1,70 @@ +// 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) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread.hpp> +#include <boost/thread/latch.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <vector> + +namespace +{ + + // Shared variables for generation latch test + const int N_THREADS = 10; + boost::latch gen_latch(N_THREADS); + boost::mutex mutex; + long global_parameter; + + void latch_thread() + { + { + boost::unique_lock<boost::mutex> lock(mutex); + global_parameter++; + } + gen_latch.count_down(); + //do something else + } + +} // namespace + +void test_latch() +{ + boost::thread_group g; + global_parameter = 0; + + try + { + for (int i = 0; i < N_THREADS; ++i) + g.create_thread(&latch_thread); + + if (! gen_latch.try_wait()) + if (gen_latch.wait_for(boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + if (gen_latch.wait_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(100)) == boost::cv_status::timeout) + gen_latch.wait(); // All the threads have been updated the global_parameter + BOOST_TEST_EQ(global_parameter, N_THREADS); + + g.join_all(); + } + catch (...) + { + BOOST_TEST(false); + g.interrupt_all(); + g.join_all(); + //throw; + } + +} + +int main() +{ + test_latch(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/test_lock_concept.cpp b/src/boost/libs/thread/test/test_lock_concept.cpp new file mode 100644 index 000000000..ba7de5cd6 --- /dev/null +++ b/src/boost/libs/thread/test/test_lock_concept.cpp @@ -0,0 +1,600 @@ +// (C) Copyright 2006-8 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: lock_concept test suite + +#include <boost/test/unit_test.hpp> +#include <boost/test/test_case_template.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/condition_variable.hpp> + +template<typename Mutex,typename Lock> +struct test_initially_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_if_other_thread_has_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_unlocked_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + Lock lock(m); + + typedef test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::try_to_lock); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + boost::unique_lock<Mutex> lock(m); + + typedef test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_locked_if_other_thread_has_shared_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_initially_locked_if_other_thread_has_shared_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + boost::shared_lock<Mutex> lock(m); + + typedef test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_unlocked_with_defer_lock_parameter +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + + BOOST_CHECK(!lock); + BOOST_CHECK(!lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_initially_locked_with_adopt_lock_parameter +{ + void operator()() const + { + Mutex m; + m.lock(); + Lock lock(m,boost::adopt_lock); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; +template<typename Mutex,typename Lock> +struct test_initially_lock_shared_with_adopt_lock_parameter +{ + void operator()() const + { + Mutex m; + m.lock_shared(); + Lock lock(m,boost::adopt_lock); + + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + + +template<typename Mutex,typename Lock> +struct test_unlocked_after_unlock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(!lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_locked_after_lock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + lock.lock(); + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_locked_after_try_lock_called +{ + void operator()() const + { + Mutex m; + Lock lock(m,boost::defer_lock); + lock.try_lock(); + BOOST_CHECK(lock); + BOOST_CHECK(lock.owns_lock()); + } +}; + +template<typename Mutex,typename Lock> +struct test_unlocked_after_try_lock_if_other_thread_has_lock +{ + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_unlocked_after_try_lock_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::defer_lock); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + + void operator()() + { + Lock lock(m); + + typedef test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock> this_type; + + boost::thread t(&this_type::locking_thread,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_lock_called_when_already_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK_THROW( lock.lock(), boost::lock_error ); + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_try_lock_called_when_already_locked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + + BOOST_CHECK_THROW( lock.try_lock(), boost::lock_error ); + } +}; + +template<typename Mutex,typename Lock> +struct test_throws_if_unlock_called_when_already_unlocked +{ + void operator()() const + { + Mutex m; + Lock lock(m); + lock.unlock(); + + BOOST_CHECK_THROW( lock.unlock(), boost::lock_error ); + } +}; +template<typename Lock> +struct test_default_constructed_has_no_mutex_and_unlocked +{ + void operator()() const + { + Lock l; + BOOST_CHECK(!l.mutex()); + BOOST_CHECK(!l.owns_lock()); + } +}; + + +template<typename Mutex,typename Lock> +struct test_locks_can_be_swapped +{ + void operator()() const + { + Mutex m1; + Mutex m2; + Mutex m3; + + Lock l1(m1); + Lock l2(m2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m1); + BOOST_CHECK_EQUAL(l2.mutex(),&m2); + + l1.swap(l2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m2); + BOOST_CHECK_EQUAL(l2.mutex(),&m1); + + swap(l1,l2); + + BOOST_CHECK_EQUAL(l1.mutex(),&m1); + BOOST_CHECK_EQUAL(l2.mutex(),&m2); + +#if 0 + l1.swap(Lock(m3)); + + BOOST_CHECK_EQUAL(l1.mutex(),&m3); +#endif + + } +}; + +template<typename Mutex,typename Lock> +void test_lock_is_scoped_lock_concept_for_mutex() +{ + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()(); +} + +typedef boost::mpl::vector<boost::mutex,boost::timed_mutex, + boost::recursive_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_lock_concept,Mutex,mutex_types_with_scoped_lock) +{ + typedef typename Mutex::scoped_lock Lock; + + test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>(); +} + +typedef boost::mpl::vector<boost::mutex,boost::timed_mutex, + boost::recursive_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,Mutex,all_mutex_types) +{ + typedef boost::unique_lock<Mutex> Lock; + + test_lock_is_scoped_lock_concept_for_mutex<Mutex,Lock>(); +} + +typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex, + boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,Mutex,mutex_types_with_scoped_try_lock) +{ + typedef typename Mutex::scoped_try_lock Lock; + + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_unlocked_after_try_lock_if_other_thread_has_lock<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); +} + +struct dummy_shared_mutex +{ + bool locked; + bool shared_locked; + bool shared_unlocked; + bool shared_timed_locked_relative; + bool shared_timed_locked_absolute; + bool timed_locked_relative; + bool timed_locked_absolute; + + dummy_shared_mutex(): + locked(false),shared_locked(false),shared_unlocked(false), + shared_timed_locked_relative(false), + shared_timed_locked_absolute(false), + timed_locked_relative(false), + timed_locked_absolute(false) + {} + + void lock() + { + locked=true; + } + + void lock_shared() + { + shared_locked=true; + } + + void unlock() + {} + + void unlock_shared() + { + shared_unlocked=true; + } + + bool timed_lock_shared(boost::system_time) + { + shared_timed_locked_absolute=true; + return false; + } + template<typename Duration> + bool timed_lock_shared(Duration) + { + shared_timed_locked_relative=true; + return false; + } + bool timed_lock(boost::system_time) + { + timed_locked_absolute=true; + return false; + } + template<typename Duration> + bool timed_lock(Duration) + { + timed_locked_relative=true; + return false; + } + +}; + + +BOOST_AUTO_TEST_CASE(test_shared_lock) +{ + typedef boost::shared_mutex Mutex; + typedef boost::shared_lock<Mutex> Lock; + + test_default_constructed_has_no_mutex_and_unlocked<Lock>()(); + test_initially_locked<Mutex,Lock>()(); + test_initially_unlocked_with_try_lock_if_other_thread_has_unique_lock<Mutex,Lock>()(); + test_initially_locked_if_other_thread_has_shared_lock<Mutex,Lock>()(); + test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()(); + test_initially_lock_shared_with_adopt_lock_parameter<Mutex,Lock>()(); + test_unlocked_after_unlock_called<Mutex,Lock>()(); + test_locked_after_lock_called<Mutex,Lock>()(); + test_locked_after_try_lock_called<Mutex,Lock>()(); + test_throws_if_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()(); + test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()(); + test_locks_can_be_swapped<Mutex,Lock>()(); + + dummy_shared_mutex dummy; + boost::shared_lock<dummy_shared_mutex> lk(dummy); + BOOST_CHECK(dummy.shared_locked); + lk.unlock(); + BOOST_CHECK(dummy.shared_unlocked); + lk.timed_lock(boost::posix_time::milliseconds(5)); + BOOST_CHECK(dummy.shared_timed_locked_relative); + lk.timed_lock(boost::get_system_time()); + BOOST_CHECK(dummy.shared_timed_locked_absolute); +} + +//boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) +//{ +// boost::unit_test::test_suite* test = +// BOOST_TEST_SUITE("Boost.Threads: lock concept test suite"); +// +// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex, +// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_lock; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_lock_concept,mutex_types_with_scoped_lock)); +// +// typedef boost::mpl::vector<boost::try_mutex,boost::timed_mutex, +// boost::recursive_try_mutex,boost::recursive_timed_mutex> mutex_types_with_scoped_try_lock; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_scoped_try_lock_concept,mutex_types_with_scoped_try_lock)); +// +// typedef boost::mpl::vector<boost::mutex,boost::try_mutex,boost::timed_mutex, +// boost::recursive_mutex,boost::recursive_try_mutex,boost::recursive_timed_mutex,boost::shared_mutex> all_mutex_types; +// +// test->add(BOOST_TEST_CASE_TEMPLATE(test_unique_lock_is_scoped_lock,all_mutex_types)); +// test->add(BOOST_TEST_CASE(&test_shared_lock)); +// +// return test; +//} + diff --git a/src/boost/libs/thread/test/test_ml.cpp b/src/boost/libs/thread/test/test_ml.cpp new file mode 100644 index 000000000..61b7eff56 --- /dev/null +++ b/src/boost/libs/thread/test/test_ml.cpp @@ -0,0 +1,201 @@ +// Copyright (C) 2010 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 <boost/config.hpp> +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include <boost/detail/lightweight_test.hpp> +#include <boost/thread/future.hpp> +#include <boost/utility/result_of.hpp> +#include <functional> + +struct async_func { + virtual ~async_func() { } + virtual void run() =0; + }; + +template <typename Ret> +class async_func_pt : public async_func { + boost::packaged_task<Ret> f; +public: + void run() { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +f(); } + async_func_pt (boost::packaged_task<Ret>&& f) : f(boost::move(f)) {} + ~async_func_pt() { } + boost::unique_future<Ret> get_future() { return f.get_future(); } + }; + +void async_core (async_func* p) { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + p->run(); +} + + + + +template <typename F> +boost::unique_future<typename boost::result_of< F() >::type> +async (F&& f) + { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + typedef typename boost::result_of< F() >::type RetType; + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + async_func_pt<RetType>* p= new async_func_pt<RetType> (boost::packaged_task<RetType>(boost::forward<F>(f))); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<RetType> future_result= p->get_future(); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + async_core (p); + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + return boost::move(future_result); + } + +template <typename F, typename A1> +boost::unique_future<typename boost::result_of< F(A1) >::type> +async (F&& f, A1&& a1) + { + std::cout << __FILE__ << ":" << __LINE__ << std::endl; +// This should be all it needs. But get a funny error deep inside Boost. +// problem overloading with && ? + return async (boost::bind(f,a1)); + } + + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + + +size_t foo (const std::string& s) + { + return s.size(); + } + + + +void test1() +{ +// this one works + // most fundimental form: + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<int> fi= async (&calculate_the_answer_to_life_the_universe_and_everything); + int i= fi.get(); + BOOST_TEST (i== 42); + + +// This one chokes at compile time + std::cout << __FILE__ << ":" << __LINE__ << std::endl; + boost::unique_future<size_t> fut_1= async (&foo, "Life"); + + BOOST_TEST (fut_1.get()== 4); +} + +int main() +{ + test1(); + return boost::report_errors(); + +} + +#else +int main() +{ + return 0; +} + +#endif +/* + * + "/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" + -o "../../../bin.v2/libs/thread/test/test_ml.test/clang-darwin-3.0x/debug/threading-multi/test_ml" + "../../../bin.v2/libs/thread/test/test_ml.test/clang-darwin-3.0x/debug/threading-multi/test_ml.o" + "../../../bin.v2/libs/test/build/clang-darwin-3.0x/debug/link-static/threading-multi/libboost_unit_test_framework.a" + "../../../bin.v2/libs/thread/build/clang-darwin-3.0x/debug/threading-multi/libboost_thread.dylib" + "../../../bin.v2/libs/chrono/build/clang-darwin-3.0x/debug/threading-multi/libboost_chrono.dylib" + "../../../bin.v2/libs/system/build/clang-darwin-3.0x/debug/threading-multi/libboost_system.dylib" -g +*/ + + +/* + * + * #include <boost/test/unit_test.hpp> +#include <boost/thread/future.hpp> +#include <boost/utility/result_of.hpp> +#include <functional> + +struct async_func { + virtual ~async_func() { } + virtual void run() =0; + }; + +template <typename Ret> +class async_func_pt : public async_func { + boost::packaged_task<Ret> f; +public: + void run() override { f(); } + async_func_pt (boost::packaged_task<Ret>&& f) : f(std::move(f)) {} + ~async_func_pt() { } + boost::unique_future<Ret> get_future() { return f.get_future(); } + }; + +void async_core (async_func* p); + + + + +template <typename F> +boost::unique_future<typename boost::result_of< F() >::type> +async (F&& f) + { + typedef typename boost::result_of< F() >::type RetType; + async_func_pt<RetType>* p= new async_func_pt<RetType> (boost::packaged_task<RetType>(f)); + boost::unique_future<RetType> future_result= p->get_future(); + async_core (p); + return std::move(future_result); + } + +template <typename F, typename A1> +boost::unique_future<typename boost::result_of< F(A1) >::type> +async (F&& f, A1&& a1) + { +// This should be all it needs. But get a funny error deep inside Boost. +// problem overloading with && ? + return async (std::tr1::bind(f,a1)); + } + +BOOST_AUTO_TEST_SUITE(thread_pool_tests) + +int calculate_the_answer_to_life_the_universe_and_everything() +{ + return 42; +} + + +size_t foo (const std::string& s) + { + return s.size(); + } + + + +BOOST_AUTO_TEST_CASE( async_test ) +{ +// this one works + // most fundimental form: + boost::unique_future<int> fi= async (&calculate_the_answer_to_life_the_universe_and_everything); + int i= fi.get(); + BOOST_CHECK_EQUAL (i, 42); + + +// This one chokes at compile time + boost::unique_future<size_t> fut_1= async (&foo, "Life"); + + BOOST_CHECK_EQUAL (fut_1.get(), 4); +} + + +BOOST_AUTO_TEST_SUITE_END() + */ diff --git a/src/boost/libs/thread/test/test_ml2.cpp b/src/boost/libs/thread/test/test_ml2.cpp new file mode 100644 index 000000000..86ff65738 --- /dev/null +++ b/src/boost/libs/thread/test/test_ml2.cpp @@ -0,0 +1,60 @@ +// Copyright (C) 2010 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 <cassert> +#include <vector> +#include <future> +#include <functional> +#include <boost/thread/future.hpp> + + +int TRUC = 42; +int main() +{ + std::vector< std::function<void()> > work_queue; + + auto do_some_work = [&]()-> boost::future<int*> + { + auto promise = std::make_shared<boost::promise<int*>>(); +#if 0 + work_queue.push_back( [=] + { + promise->set_value( &TRUC ); + }); +#else + auto inner = [=]() + { + promise->set_value( &TRUC ); + }; + work_queue.push_back(inner); + +#endif + + return promise->get_future(); + + }; + + auto ft_value = do_some_work(); + + while( !work_queue.empty() ) + { +#if 0 + auto work = work_queue.back(); +#else + std::function<void()> work; + work = work_queue.back(); +#endif + work_queue.pop_back(); + work(); + } + + auto value = ft_value.get(); + assert( value == &TRUC ); + return 0; +} + + diff --git a/src/boost/libs/thread/test/test_move_function.cpp b/src/boost/libs/thread/test/test_move_function.cpp new file mode 100644 index 000000000..6922fbe64 --- /dev/null +++ b/src/boost/libs/thread/test/test_move_function.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: move function test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/shared_ptr.hpp> + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_construction) +{ + boost::thread src(&do_nothing); + boost::thread::id src_id=src.get_id(); + boost::thread dest(boost::move(src)); + boost::thread::id dest_id=dest.get_id(); + BOOST_CHECK(src_id==dest_id); + BOOST_CHECK(src.get_id()==boost::thread::id()); + dest.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_lvalue_on_assignment) +{ + boost::thread src(&do_nothing); + boost::thread::id src_id=src.get_id(); + boost::thread dest; + dest=boost::move(src); + boost::thread::id dest_id=dest.get_id(); + BOOST_CHECK(src_id==dest_id); + BOOST_CHECK(src.get_id()==boost::thread::id()); + dest.join(); +} + +boost::thread start_thread() +{ + return boost::thread(&do_nothing); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_on_construction) +{ + boost::thread x(start_thread()); + BOOST_CHECK(x.get_id()!=boost::thread::id()); + x.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_move_from_rvalue_using_explicit_move) +{ + //boost::thread x(boost::move(start_thread())); + boost::thread x=start_thread(); + BOOST_CHECK(x.get_id()!=boost::thread::id()); + x.join(); +} + +BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction) +{ + boost::mutex m; + boost::unique_lock<boost::mutex> l(m); + BOOST_CHECK(l.owns_lock()); + BOOST_CHECK(l.mutex()==&m); + + boost::unique_lock<boost::mutex> l2(boost::move(l)); + BOOST_CHECK(!l.owns_lock()); + BOOST_CHECK(!l.mutex()); + BOOST_CHECK(l2.owns_lock()); + BOOST_CHECK(l2.mutex()==&m); +} + +boost::unique_lock<boost::mutex> get_lock(boost::mutex& m) +{ + return boost::unique_lock<boost::mutex>(m); +} + + +BOOST_AUTO_TEST_CASE(test_unique_lock_move_from_rvalue_on_construction) +{ + boost::mutex m; + boost::unique_lock<boost::mutex> l(get_lock(m)); + BOOST_CHECK(l.owns_lock()); + BOOST_CHECK(l.mutex()==&m); +} + +namespace user_test_ns +{ + template<typename T> + T move(T& t) + { + return t.move(); + } + + bool move_called=false; + + struct nc: + public boost::shared_ptr<int> + { +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nc() {} + nc(nc&&) + { + move_called=true; + } +#endif + nc move() + { + move_called=true; + return nc(); + } + }; +} + +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE(user_test_ns::nc) +} + +BOOST_AUTO_TEST_CASE(test_move_for_user_defined_type_unaffected) +{ + user_test_ns::nc src; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + user_test_ns::nc dest=boost::move(src); +#else + user_test_ns::nc dest=move(src); +#endif + BOOST_CHECK(user_test_ns::move_called); +} + + + + diff --git a/src/boost/libs/thread/test/test_mutex.cpp b/src/boost/libs/thread/test/test_mutex.cpp new file mode 100644 index 000000000..e6ac24e27 --- /dev/null +++ b/src/boost/libs/thread/test/test_mutex.cpp @@ -0,0 +1,341 @@ +// 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 +#define BOOST_TEST_MODULE Boost.Threads: mutex test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/thread/condition.hpp> + +#define BOOST_TEST_MODULE Boost.Threads: mutex test suite + +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +template <typename M> +struct test_lock +{ + typedef M mutex_type; + typedef typename M::scoped_lock lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt = delay(0, 100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock ? true : false); + + // Test the lock and unlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + } +}; + +template <typename M> +struct test_trylock +{ + typedef M mutex_type; + typedef typename M::scoped_try_lock try_lock_type; + + void operator()() + { + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + try_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + } + { + try_lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + try_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::xtime xt = delay(0, 100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, xt)); + BOOST_CHECK(lock ? true : false); + + // Test the lock, unlock and trylock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + BOOST_CHECK(lock.try_lock()); + BOOST_CHECK(lock ? true : false); + } +}; + +template<typename Mutex> +struct test_lock_times_out_if_other_thread_has_lock +{ + typedef boost::unique_lock<Mutex> Lock; + + Mutex m; + boost::mutex done_mutex; + bool done; + bool locked; + boost::condition_variable done_cond; + + test_lock_times_out_if_other_thread_has_lock(): + done(false),locked(false) + {} + + void locking_thread() + { + Lock lock(m,boost::defer_lock); + lock.timed_lock(boost::posix_time::milliseconds(50)); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + void locking_thread_through_constructor() + { + Lock lock(m,boost::posix_time::milliseconds(50)); + + boost::lock_guard<boost::mutex> lk(done_mutex); + locked=lock.owns_lock(); + done=true; + done_cond.notify_one(); + } + + bool is_done() const + { + return done; + } + + typedef test_lock_times_out_if_other_thread_has_lock<Mutex> this_type; + + void do_test(void (this_type::*test_func)()) + { + Lock lock(m); + + locked=false; + done=false; + + boost::thread t(test_func,this); + + try + { + { + boost::unique_lock<boost::mutex> lk(done_mutex); + BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2), + boost::bind(&this_type::is_done,this))); + BOOST_CHECK(!locked); + } + + lock.unlock(); + t.join(); + } + catch(...) + { + lock.unlock(); + t.join(); + throw; + } + } + + + void operator()() + { + do_test(&this_type::locking_thread); + do_test(&this_type::locking_thread_through_constructor); + } +}; + +template <typename M> +struct test_timedlock +{ + typedef M mutex_type; + typedef typename M::scoped_timed_lock timed_lock_type; + + static bool fake_predicate() + { + return false; + } + + void operator()() + { + test_lock_times_out_if_other_thread_has_lock<mutex_type>()(); + + mutex_type mutex; + boost::condition condition; + + // Test the lock's constructors. + { + // Construct and initialize an xtime for a fast time out. + boost::system_time xt = boost::get_system_time()+boost::posix_time::milliseconds(100); + + timed_lock_type lock(mutex, xt); + BOOST_CHECK(lock ? true : false); + } + { + timed_lock_type lock(mutex, boost::defer_lock); + BOOST_CHECK(!lock); + } + timed_lock_type lock(mutex); + BOOST_CHECK(lock ? true : false); + + // Construct and initialize an xtime for a fast time out. + boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100); + + // Test the lock and the mutex with condition variables. + // No one is going to notify this condition variable. We expect to + // time out. + BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate)); + BOOST_CHECK(lock ? true : false); + + boost::system_time now=boost::get_system_time(); + boost::posix_time::milliseconds const timeout_resolution(20); + BOOST_CHECK((timeout-timeout_resolution)<now); + + // Test the lock, unlock and timedlock methods. + lock.unlock(); + BOOST_CHECK(!lock); + lock.lock(); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100); + BOOST_CHECK(lock.timed_lock(target)); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + + BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100))); + mutex.unlock(); + + BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100))); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + + } +}; + +template <typename M> +struct test_recursive_lock +{ + typedef M mutex_type; + typedef typename M::scoped_lock lock_type; + + void operator()() + { + mutex_type mx; + lock_type lock1(mx); + lock_type lock2(mx); + } +}; + + +void do_test_mutex() +{ + test_lock<boost::mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_mutex) +{ + timed_test(&do_test_mutex, 3); +} + +void do_test_try_mutex() +{ + test_lock<boost::try_mutex>()(); + test_trylock<boost::try_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_try_mutex) +{ + timed_test(&do_test_try_mutex, 3); +} + +void do_test_timed_mutex() +{ + test_lock<boost::timed_mutex>()(); + test_trylock<boost::timed_mutex>()(); + test_timedlock<boost::timed_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_timed_mutex) +{ + timed_test(&do_test_timed_mutex, 3); +} + +void do_test_recursive_mutex() +{ + test_lock<boost::recursive_mutex>()(); + test_recursive_lock<boost::recursive_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_mutex) +{ + timed_test(&do_test_recursive_mutex, 3); +} + +void do_test_recursive_try_mutex() +{ + test_lock<boost::recursive_try_mutex>()(); + test_trylock<boost::recursive_try_mutex>()(); + test_recursive_lock<boost::recursive_try_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_try_mutex) +{ + timed_test(&do_test_recursive_try_mutex, 3); +} + +void do_test_recursive_timed_mutex() +{ + test_lock<boost::recursive_timed_mutex>()(); + test_trylock<boost::recursive_timed_mutex>()(); + test_timedlock<boost::recursive_timed_mutex>()(); + test_recursive_lock<boost::recursive_timed_mutex>()(); +} + +BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex) +{ + timed_test(&do_test_recursive_timed_mutex, 3); +} + + + diff --git a/src/boost/libs/thread/test/test_once.cpp b/src/boost/libs/thread/test/test_once.cpp new file mode 100644 index 000000000..3103f1c23 --- /dev/null +++ b/src/boost/libs/thread/test/test_once.cpp @@ -0,0 +1,192 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: once test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/once.hpp> +#include <iostream> + +#include <boost/thread/detail/log.hpp> + +boost::once_flag flag=BOOST_ONCE_INIT; +int var_to_init=0; +boost::mutex m; + +void initialize_variable() +{ + // ensure that if multiple threads get in here, they are serialized, so we can see the effect + boost::unique_lock<boost::mutex> lock(m); + ++var_to_init; +} + + +void call_once_thread() +{ + unsigned const loop_count=100; + int my_once_value=0; + for(unsigned i=0;i<loop_count;++i) + { + boost::call_once(flag, &initialize_variable); + my_once_value=var_to_init; + if(my_once_value!=1) + { + break; + } + } + boost::unique_lock<boost::mutex> lock(m); + BOOST_CHECK_EQUAL(my_once_value, 1); +} + +BOOST_AUTO_TEST_CASE(test_call_once) +{ + BOOST_DETAIL_THREAD_LOG; + + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_thread); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(var_to_init,1); +} + +int var_to_init_with_functor=0; + +struct increment_value +{ + int* value; + explicit increment_value(int* value_): + value(value_) + {} + + void operator()() const + { + boost::unique_lock<boost::mutex> lock(m); + ++(*value); + } +}; + +void call_once_with_functor() +{ + unsigned const loop_count=100; + int my_once_value=0; + static boost::once_flag functor_flag=BOOST_ONCE_INIT; + for(unsigned i=0;i<loop_count;++i) + { + boost::call_once(functor_flag, increment_value(&var_to_init_with_functor)); + my_once_value=var_to_init_with_functor; + if(my_once_value!=1) + { + break; + } + } + boost::unique_lock<boost::mutex> lock(m); + BOOST_CHECK_EQUAL(my_once_value, 1); +} + +BOOST_AUTO_TEST_CASE(test_call_once_arbitrary_functor) +{ + BOOST_DETAIL_THREAD_LOG; + + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_with_functor); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(var_to_init_with_functor,1); +} + + +struct throw_before_third_pass +{ + struct my_exception + {}; + + static unsigned pass_counter; + + void operator()() const + { + boost::unique_lock<boost::mutex> lock(m); + ++pass_counter; + if(pass_counter<3) + { + throw my_exception(); + } + } +}; + +unsigned throw_before_third_pass::pass_counter=0; +unsigned exception_counter=0; + +void call_once_with_exception() +{ + static boost::once_flag functor_flag=BOOST_ONCE_INIT; + try + { + boost::call_once(functor_flag, throw_before_third_pass()); + } + catch(throw_before_third_pass::my_exception) + { + boost::unique_lock<boost::mutex> lock(m); + ++exception_counter; + } +} + +BOOST_AUTO_TEST_CASE(test_call_once_retried_on_exception) +{ + BOOST_DETAIL_THREAD_LOG; + unsigned const num_threads=20; + boost::thread_group group; + + try + { + for(unsigned i=0;i<num_threads;++i) + { + group.create_thread(&call_once_with_exception); + } + group.join_all(); + } + catch(...) + { + group.interrupt_all(); + group.join_all(); + throw; + } + + BOOST_CHECK_EQUAL(throw_before_third_pass::pass_counter,3u); + BOOST_CHECK_EQUAL(exception_counter,2u); +} + + diff --git a/src/boost/libs/thread/test/test_physical_concurrency.cpp b/src/boost/libs/thread/test/test_physical_concurrency.cpp new file mode 100644 index 000000000..5c635751f --- /dev/null +++ b/src/boost/libs/thread/test/test_physical_concurrency.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2013 Tim Blechmann +// +// 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_TEST_MODULE Boost.Threads: physical_concurrency test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> + +BOOST_AUTO_TEST_CASE(test_physical_concurrency_is_non_zero) +{ +#if defined(__MINGW32__) && !defined(__MINGW64__) +// This matches the condition in win32/thread.cpp, even though +// that's probably wrong on MinGW-w64 in 32 bit mode +#else + BOOST_CHECK(boost::thread::physical_concurrency()!=0); +#endif +} + + + + diff --git a/src/boost/libs/thread/test/test_scheduled_tp.cpp b/src/boost/libs/thread/test/test_scheduled_tp.cpp new file mode 100644 index 000000000..8684ffd4f --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduled_tp.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/bind/bind.hpp> +#include <boost/chrono.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <boost/function.hpp> +#include <boost/thread/executors/scheduled_thread_pool.hpp> +#include <iostream> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + +typedef boost::scheduled_thread_pool scheduled_tp; + +void fn(int x) +{ + std::cout << x << std::endl; +} + +void func(steady_clock::time_point pushed, steady_clock::duration dur) +{ + BOOST_TEST(pushed + dur < steady_clock::now()); +} +void func2(scheduled_tp* tp, steady_clock::duration d) +{ + boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + tp->submit_after(fn, d); +} + + + +void test_timing(const int n) +{ + //This function should take n seconds to execute. + boost::scheduled_thread_pool se(4); + + for(int i = 1; i <= n; i++) + { + se.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + //dtor is called here so all task will have to be executed before we return +} + +void test_deque_timing() +{ + boost::scheduled_thread_pool se(4); + for(int i = 0; i < 10; i++) + { + steady_clock::duration d = milliseconds(i*100); + boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + se.submit_after(fn,d); + } +} + +void test_deque_multi(const int n) +{ + scheduled_tp se(4); + boost::thread_group tg; + for(int i = 0; i < n; i++) + { + steady_clock::duration d = milliseconds(i*100); + //boost::function<void()> fn = boost::bind(func,steady_clock::now(),d); + //tg.create_thread(boost::bind(boost::mem_fn(&scheduled_tp::submit_after), &se, fn, d)); + tg.create_thread(boost::bind(func2, &se, d)); + } + tg.join_all(); + //dtor is called here so execution will block until all the closures + //have been completed. +} + +int main() +{ + steady_clock::time_point start = steady_clock::now(); + test_timing(5); + steady_clock::duration diff = steady_clock::now() - start; + BOOST_TEST(diff > milliseconds(500)); + test_deque_timing(); + test_deque_multi(4); + test_deque_multi(8); + test_deque_multi(16); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_scheduler.cpp b/src/boost/libs/thread/test/test_scheduler.cpp new file mode 100644 index 000000000..5847ff010 --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduler.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/thread/executors/scheduler.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/chrono/chrono_io.hpp> +#include <iostream> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + + +typedef boost::executors::basic_thread_pool thread_pool; + +void fn(int x) +{ + //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl; + std::cout << x << std::endl; +} + +void test_scheduler(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.submit_after(boost::bind(fn,i), seconds(i)); + sch.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } +} + +void test_after(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.after(seconds(i)).submit(boost::bind(fn,i)); + sch.after(milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +void test_at(const int n, boost::scheduler<>& sch) +{ + for(int i = 1; i <= n; i++) + { + sch.at(steady_clock::now()+seconds(i)).submit(boost::bind(fn,i)); + sch.at(steady_clock::now()+milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +void test_on(const int n, boost::scheduler<>& sch, thread_pool& tp) +{ + for(int i = 1; i <= n; i++) + { + sch.on(tp).after(seconds(i)).submit(boost::bind(fn,i)); + sch.on(tp).after(milliseconds(i*100)).submit(boost::bind(fn,i)); + } +} + +int main() +{ + thread_pool tp(4); + boost::scheduler<> sch; + test_scheduler(5, sch); + test_after(5, sch); + test_at(5, sch); + test_on(5, sch, tp); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_scheduling_adaptor.cpp b/src/boost/libs/thread/test/test_scheduling_adaptor.cpp new file mode 100644 index 000000000..38c073bda --- /dev/null +++ b/src/boost/libs/thread/test/test_scheduling_adaptor.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 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 <boost/config.hpp> +#if ! defined BOOST_NO_CXX11_DECLTYPE +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#define BOOST_THREAD_VERSION 4 +#define BOOST_THREAD_PROVIDES_EXECUTORS + +#include <boost/function.hpp> +#include <boost/thread/executors/executor.hpp> +#include <boost/thread/executors/basic_thread_pool.hpp> +#include <boost/thread/executors/scheduling_adaptor.hpp> +#include <boost/chrono/chrono_io.hpp> + +#include <boost/core/lightweight_test.hpp> + +using namespace boost::chrono; + + +typedef boost::executors::basic_thread_pool thread_pool; + +void fn(int x) +{ + //std::cout << "[" << __LINE__ << "] " << steady_clock::now() << std::endl; + std::cout << x << std::endl; +} + +void test_timing(const int n) +{ + thread_pool tp(4); + boost::scheduling_adaptor<thread_pool> sa(tp); + for(int i = 1; i <= n; i++) + { + sa.submit_after(boost::bind(fn,i),seconds(i)); + sa.submit_after(boost::bind(fn,i), milliseconds(i*100)); + } + boost::this_thread::sleep_for(boost::chrono::seconds(10)); +} + +int main() +{ + steady_clock::time_point start = steady_clock::now(); + test_timing(5); + steady_clock::duration diff = steady_clock::now() - start; + BOOST_TEST(diff > seconds(5)); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_shared_mutex.cpp b/src/boost/libs/thread/test/test_shared_mutex.cpp new file mode 100644 index 000000000..17bd9a6a1 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex.cpp @@ -0,0 +1,281 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" +#include <iostream> + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + +BOOST_AUTO_TEST_CASE(test_multiple_readers) +{ + std::cout << __LINE__ << std::endl; + unsigned const number_of_threads=10; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<number_of_threads) + { + unblocked_condition.wait(lk); + } + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads); +} + +BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted) +{ + std::cout << __LINE__ << std::endl; + unsigned const number_of_threads=10; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + boost::thread::sleep(delay(2)); + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_reader_blocks_writer) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<1) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + boost::unique_lock<boost::shared_mutex> write_lock(rw_mutex); + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + unsigned const reader_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,0U); + + write_lock.unlock(); + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<reader_count) + { + unblocked_condition.wait(lk); + } + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); + + finish_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count); +} + +BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer) +{ + std::cout << __LINE__ << std::endl; + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_readers=0; + unsigned max_simultaneous_readers=0; + unsigned simultaneous_running_writers=0; + unsigned max_simultaneous_writers=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_reading_mutex; + boost::unique_lock<boost::mutex> finish_reading_lock(finish_reading_mutex); + boost::mutex finish_writing_mutex; + boost::unique_lock<boost::mutex> finish_writing_lock(finish_writing_mutex); + + unsigned const reader_count=10; + unsigned const writer_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_reading_mutex,simultaneous_running_readers,max_simultaneous_readers)); + } + boost::thread::sleep(delay(1)); + for(unsigned i=0;i<writer_count;++i) + { + pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers)); + } + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<reader_count) + { + unblocked_condition.wait(lk); + } + } + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count); + + finish_reading_lock.unlock(); + + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<(reader_count+1)) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + + finish_writing_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u); +} diff --git a/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp b/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp new file mode 100644 index 000000000..d395b2e78 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_part_2.cpp @@ -0,0 +1,294 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite + +#include <boost/config.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + +class simple_upgrade_thread +{ + boost::shared_mutex& rwm; + boost::mutex& finish_mutex; + boost::mutex& unblocked_mutex; + unsigned& unblocked_count; + + void operator=(simple_upgrade_thread&); + +public: + simple_upgrade_thread(boost::shared_mutex& rwm_, + boost::mutex& finish_mutex_, + boost::mutex& unblocked_mutex_, + unsigned& unblocked_count_): + rwm(rwm_),finish_mutex(finish_mutex_), + unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_) + {} + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + simple_upgrade_thread(simple_upgrade_thread const&) = default; +#endif + + void operator()() + { + boost::upgrade_lock<boost::shared_mutex> lk(rwm); + + { + boost::unique_lock<boost::mutex> ulk(unblocked_mutex); + ++unblocked_count; + } + + boost::unique_lock<boost::mutex> flk(finish_mutex); + } +}; + + +BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted) +{ + unsigned const number_of_threads=2; + + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + try + { + for(unsigned i=0;i<number_of_threads;++i) + { + pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + + boost::thread::sleep(delay(1)); + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U); + + finish_lock.unlock(); + + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u); +} + +BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared) +{ + boost::thread_group pool; + + boost::shared_mutex rw_mutex; + unsigned unblocked_count=0; + unsigned simultaneous_running_count=0; + unsigned max_simultaneous_running=0; + boost::mutex unblocked_count_mutex; + boost::condition_variable unblocked_condition; + boost::mutex finish_mutex; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + + unsigned const reader_count=10; + + try + { + for(unsigned i=0;i<reader_count;++i) + { + pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + } + boost::thread::sleep(delay(1)); + pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition, + finish_mutex,simultaneous_running_count,max_simultaneous_running)); + { + boost::unique_lock<boost::mutex> lk(unblocked_count_mutex); + while(unblocked_count<(reader_count+1)) + { + unblocked_condition.wait(lk); + } + } + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + + finish_lock.unlock(); + pool.join_all(); + } + catch(...) + { + pool.interrupt_all(); + pool.join_all(); + throw; + } + + + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1); + CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1); +} + +BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade) +{ + boost::shared_mutex mtx; + boost::upgrade_lock<boost::shared_mutex> l(mtx); + boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l); + BOOST_CHECK(ul.owns_lock()); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true) +{ + boost::shared_mutex rw_mutex; + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } +} + +BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true) +{ + boost::shared_mutex rw_mutex; + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_shared(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false) +{ + + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_upgrade_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + bool const try_succeeded=rw_mutex.try_lock_upgrade(); + BOOST_CHECK(!try_succeeded); + if(try_succeeded) + { + rw_mutex.unlock_upgrade(); + } + + finish_lock.unlock(); + writer.join(); +} + + diff --git a/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp b/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp new file mode 100644 index 000000000..c29c4260c --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_timed_locks.cpp @@ -0,0 +1,255 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_timed_locks test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK(boost::get_system_time()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK(boost::get_system_time()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::thread::sleep(delay(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + boost::posix_time::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + boost::system_time const timeout2=boost::get_system_time()+wait_duration; + timed_lock_succeeded=rw_mutex.timed_lock(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::system_time const start=boost::get_system_time(); + boost::system_time const timeout=start+boost::posix_time::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.timed_lock(timeout); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::posix_time::milliseconds const wait_duration(500); + timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + diff --git a/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp b/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp new file mode 100644 index 000000000..f746f50a9 --- /dev/null +++ b/src/boost/libs/thread/test/test_shared_mutex_timed_locks_chrono.cpp @@ -0,0 +1,259 @@ +// (C) Copyright 2006-7 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: shared_mutex_locks_chrono test suite + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/shared_mutex.hpp> +#include "./util.inl" +#include "./shared_mutex_locking_thread.hpp" + +#if defined BOOST_THREAD_USES_CHRONO + +#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ + { \ + boost::unique_lock<boost::mutex> lock(mutex_name); \ + BOOST_CHECK_EQUAL(value,expected_value); \ + } + + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_shared_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_shared_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_write_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + writer.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_succeeds_if_no_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK(boost::chrono::steady_clock::now()<timeout2); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + boost::chrono::milliseconds const timeout_resolution(50); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK((timeout-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + boost::chrono::steady_clock::time_point const timeout2=boost::chrono::steady_clock::now()+wait_duration; + timed_lock_succeeded=rw_mutex.try_lock_for(wait_duration); + BOOST_CHECK((timeout2-timeout_resolution)<boost::chrono::steady_clock::now()); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + finish_lock.unlock(); + reader.join(); +} + +BOOST_AUTO_TEST_CASE(test_timed_lock_times_out_but_read_lock_succeeds_if_read_lock_held) +{ + boost::shared_mutex rw_mutex; + boost::mutex finish_mutex; + boost::mutex unblocked_mutex; + unsigned unblocked_count=0; + boost::unique_lock<boost::mutex> finish_lock(finish_mutex); + boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count)); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u); + + boost::chrono::steady_clock::time_point const start=boost::chrono::steady_clock::now(); + boost::chrono::steady_clock::time_point const timeout=start+boost::chrono::milliseconds(500); + bool timed_lock_succeeded=rw_mutex.try_lock_until(timeout); + BOOST_CHECK(!timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock(); + } + + boost::chrono::milliseconds const wait_duration(500); + timed_lock_succeeded=rw_mutex.try_lock_shared_for(wait_duration); + BOOST_CHECK(timed_lock_succeeded); + if(timed_lock_succeeded) + { + rw_mutex.unlock_shared(); + } + + finish_lock.unlock(); + reader.join(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + + diff --git a/src/boost/libs/thread/test/test_thread.cpp b/src/boost/libs/thread/test/test_thread.cpp new file mode 100644 index 000000000..ab9ddba0d --- /dev/null +++ b/src/boost/libs/thread/test/test_thread.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/xtime.hpp> +#include <boost/bind/bind.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> + +#define BOOST_TEST_MODULE Boost.Threads: thread test suite + +#include <boost/test/unit_test.hpp> + +#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only +#include "./util.inl" + +int test_value; + +void simple_thread() +{ + test_value = 999; +} + +void comparison_thread(boost::thread::id parent) +{ + boost::thread::id const my_id=boost::this_thread::get_id(); + + BOOST_CHECK(my_id != parent); + boost::thread::id const my_id2=boost::this_thread::get_id(); + BOOST_CHECK(my_id == my_id2); + + boost::thread::id const no_thread_id=boost::thread::id(); + BOOST_CHECK(my_id != no_thread_id); +} + +BOOST_AUTO_TEST_CASE(test_sleep) +{ + boost::xtime xt = delay(3); + boost::thread::sleep(xt); + + // Ensure it's in a range instead of checking actual equality due to time + // lapse + BOOST_CHECK(boost::threads::test::in_range(xt, 2)); +} + +void do_test_creation() +{ + test_value = 0; + boost::thread thrd(&simple_thread); + thrd.join(); + BOOST_CHECK_EQUAL(test_value, 999); +} + +BOOST_AUTO_TEST_CASE(test_creation) +{ + timed_test(&do_test_creation, 1); +} + +void do_test_id_comparison() +{ + boost::thread::id const self=boost::this_thread::get_id(); + boost::thread thrd(boost::bind(&comparison_thread, self)); + thrd.join(); +} + +BOOST_AUTO_TEST_CASE(test_id_comparison) +{ + timed_test(&do_test_id_comparison, 1); +} + +void interruption_point_thread(boost::mutex* m,bool* failed) +{ + boost::unique_lock<boost::mutex> lk(*m); + boost::this_thread::interruption_point(); + *failed=true; +} + +void do_test_thread_interrupts_at_interruption_point() +{ + boost::mutex m; + bool failed=false; + boost::unique_lock<boost::mutex> lk(m); + boost::thread thrd(boost::bind(&interruption_point_thread,&m,&failed)); + thrd.interrupt(); + lk.unlock(); + thrd.join(); + BOOST_CHECK(!failed); +} + +BOOST_AUTO_TEST_CASE(test_thread_interrupts_at_interruption_point) +{ + timed_test(&do_test_thread_interrupts_at_interruption_point, 1); +} + +void disabled_interruption_point_thread(boost::mutex* m,bool* failed) +{ + boost::unique_lock<boost::mutex> lk(*m); + boost::this_thread::disable_interruption dc; + boost::this_thread::interruption_point(); + *failed=false; +} + +void do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point() +{ + boost::mutex m; + bool failed=true; + boost::unique_lock<boost::mutex> lk(m); + boost::thread thrd(boost::bind(&disabled_interruption_point_thread,&m,&failed)); + thrd.interrupt(); + lk.unlock(); + thrd.join(); + BOOST_CHECK(!failed); +} + +BOOST_AUTO_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point) +{ + timed_test(&do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point, 1); +} + +struct non_copyable_functor: + boost::noncopyable +{ + unsigned value; + + non_copyable_functor(): boost::noncopyable(), + value(0) + {} + + void operator()() + { + value=999; + } +}; + +void do_test_creation_through_reference_wrapper() +{ + non_copyable_functor f; + + boost::thread thrd(boost::ref(f)); + thrd.join(); + BOOST_CHECK_EQUAL(f.value, 999u); +} + +BOOST_AUTO_TEST_CASE(test_creation_through_reference_wrapper) +{ + timed_test(&do_test_creation_through_reference_wrapper, 1); +} + +struct long_running_thread +{ + boost::condition_variable cond; + boost::mutex mut; + bool done; + + long_running_thread(): + done(false) + {} + + void operator()() + { + boost::unique_lock<boost::mutex> lk(mut); + while(!done) + { + cond.wait(lk); + } + } +}; + +void do_test_timed_join() +{ + long_running_thread f; + boost::thread thrd(boost::ref(f)); + BOOST_CHECK(thrd.joinable()); + boost::system_time xt=delay(3); + bool const joined=thrd.timed_join(xt); + BOOST_CHECK(boost::threads::test::in_range(boost::get_xtime(xt), 2)); + BOOST_CHECK(!joined); + BOOST_CHECK(thrd.joinable()); + { + boost::unique_lock<boost::mutex> lk(f.mut); + f.done=true; + f.cond.notify_one(); + } + + xt=delay(3); + bool const joined2=thrd.timed_join(xt); + boost::system_time const now=boost::get_system_time(); + BOOST_CHECK(xt>now); + BOOST_CHECK(joined2); + BOOST_CHECK(!thrd.joinable()); +} + +BOOST_AUTO_TEST_CASE(test_timed_join) +{ + timed_test(&do_test_timed_join, 10); +} + +BOOST_AUTO_TEST_CASE(test_swap) +{ + boost::thread t(&simple_thread); + boost::thread t2(&simple_thread); + boost::thread::id id1=t.get_id(); + boost::thread::id id2=t2.get_id(); + + t.swap(t2); + BOOST_CHECK(t.get_id()==id2); + BOOST_CHECK(t2.get_id()==id1); + + swap(t,t2); + BOOST_CHECK(t.get_id()==id1); + BOOST_CHECK(t2.get_id()==id2); +} + diff --git a/src/boost/libs/thread/test/test_thread_exit.cpp b/src/boost/libs/thread/test/test_thread_exit.cpp new file mode 100644 index 000000000..577bcd05d --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_exit.cpp @@ -0,0 +1,63 @@ +// (C) Copyright 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/future.hpp> +#include <utility> +#include <memory> +#include <string> + +#define BOOST_TEST_MODULE Boost.Threads: thread exit test suite + +#include <boost/test/unit_test.hpp> + +boost::thread::id exit_func_thread_id; + +void exit_func() +{ + exit_func_thread_id=boost::this_thread::get_id(); +} + +void tf1() +{ + boost::this_thread::at_thread_exit(exit_func); + BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id()); +} + +BOOST_AUTO_TEST_CASE(test_thread_exit_func_runs_when_thread_exits) +{ + exit_func_thread_id=boost::thread::id(); + boost::thread t(&tf1); + boost::thread::id const t_id=t.get_id(); + t.join(); + BOOST_CHECK(exit_func_thread_id==t_id); +} + +struct fo +{ + void operator()() + { + exit_func_thread_id=boost::this_thread::get_id(); + } +}; + +void tf2() +{ + boost::this_thread::at_thread_exit(fo()); + BOOST_CHECK(exit_func_thread_id!=boost::this_thread::get_id()); +} + + +BOOST_AUTO_TEST_CASE(test_can_use_function_object_for_exit_func) +{ + exit_func_thread_id=boost::thread::id(); + boost::thread t(tf2); + boost::thread::id const t_id=t.get_id(); + t.join(); + BOOST_CHECK(exit_func_thread_id==t_id); +} diff --git a/src/boost/libs/thread/test/test_thread_id.cpp b/src/boost/libs/thread/test/test_thread_id.cpp new file mode 100644 index 000000000..477909d1a --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_id.cpp @@ -0,0 +1,139 @@ +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: thread::get_id test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/bind/bind.hpp> + +void do_nothing() +{} + +BOOST_AUTO_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id) +{ + boost::thread t; + BOOST_CHECK(t.get_id()==boost::thread::id()); +} + +BOOST_AUTO_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id) +{ + boost::thread t(&do_nothing); + BOOST_CHECK(t.get_id()!=boost::thread::id()); + t.join(); +} + +BOOST_AUTO_TEST_CASE(test_different_threads_have_different_ids) +{ + boost::thread t(do_nothing); + boost::thread t2(do_nothing); + BOOST_CHECK(t.get_id()!=t2.get_id()); + t.join(); + t2.join(); +} + +BOOST_AUTO_TEST_CASE(test_thread_ids_have_a_total_order) +{ + boost::thread t(do_nothing); + boost::thread t2(do_nothing); + boost::thread t3(do_nothing); + BOOST_CHECK(t.get_id()!=t2.get_id()); + BOOST_CHECK(t.get_id()!=t3.get_id()); + BOOST_CHECK(t2.get_id()!=t3.get_id()); + + BOOST_CHECK((t.get_id()<t2.get_id()) != (t2.get_id()<t.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) != (t3.get_id()<t.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) != (t3.get_id()<t2.get_id())); + + BOOST_CHECK((t.get_id()>t2.get_id()) != (t2.get_id()>t.get_id())); + BOOST_CHECK((t.get_id()>t3.get_id()) != (t3.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()>t3.get_id()) != (t3.get_id()>t2.get_id())); + + BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>t2.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>t.get_id())); + BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>t3.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>t2.get_id())); + BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>t3.get_id())); + + BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>=t.get_id())); + BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>=t2.get_id())); + BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>=t.get_id())); + BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>=t3.get_id())); + BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>=t2.get_id())); + BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>=t3.get_id())); + + BOOST_CHECK((t.get_id()<=t2.get_id()) == (t2.get_id()>t.get_id())); + BOOST_CHECK((t2.get_id()<=t.get_id()) == (t.get_id()>t2.get_id())); + BOOST_CHECK((t.get_id()<=t3.get_id()) == (t3.get_id()>t.get_id())); + BOOST_CHECK((t3.get_id()<=t.get_id()) == (t.get_id()>t3.get_id())); + BOOST_CHECK((t2.get_id()<=t3.get_id()) == (t3.get_id()>t2.get_id())); + BOOST_CHECK((t3.get_id()<=t2.get_id()) == (t2.get_id()>t3.get_id())); + + if((t.get_id()<t2.get_id()) && (t2.get_id()<t3.get_id())) + { + BOOST_CHECK(t.get_id()<t3.get_id()); + } + else if((t.get_id()<t3.get_id()) && (t3.get_id()<t2.get_id())) + { + BOOST_CHECK(t.get_id()<t2.get_id()); + } + else if((t2.get_id()<t3.get_id()) && (t3.get_id()<t.get_id())) + { + BOOST_CHECK(t2.get_id()<t.get_id()); + } + else if((t2.get_id()<t.get_id()) && (t.get_id()<t3.get_id())) + { + BOOST_CHECK(t2.get_id()<t3.get_id()); + } + else if((t3.get_id()<t.get_id()) && (t.get_id()<t2.get_id())) + { + BOOST_CHECK(t3.get_id()<t2.get_id()); + } + else if((t3.get_id()<t2.get_id()) && (t2.get_id()<t.get_id())) + { + BOOST_CHECK(t3.get_id()<t.get_id()); + } + else + { + BOOST_CHECK(false); + } + + boost::thread::id default_id; + + BOOST_CHECK(default_id < t.get_id()); + BOOST_CHECK(default_id < t2.get_id()); + BOOST_CHECK(default_id < t3.get_id()); + + BOOST_CHECK(default_id <= t.get_id()); + BOOST_CHECK(default_id <= t2.get_id()); + BOOST_CHECK(default_id <= t3.get_id()); + + BOOST_CHECK(!(default_id > t.get_id())); + BOOST_CHECK(!(default_id > t2.get_id())); + BOOST_CHECK(!(default_id > t3.get_id())); + + BOOST_CHECK(!(default_id >= t.get_id())); + BOOST_CHECK(!(default_id >= t2.get_id())); + BOOST_CHECK(!(default_id >= t3.get_id())); + + t.join(); + t2.join(); + t3.join(); +} + +void get_thread_id(boost::thread::id* id) +{ + *id=boost::this_thread::get_id(); +} + +BOOST_AUTO_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id) +{ + boost::thread::id id; + boost::thread t(boost::bind(get_thread_id,&id)); + boost::thread::id t_id=t.get_id(); + t.join(); + BOOST_CHECK(id==t_id); +} diff --git a/src/boost/libs/thread/test/test_thread_launching.cpp b/src/boost/libs/thread/test/test_thread_launching.cpp new file mode 100644 index 000000000..0c74871d3 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_launching.cpp @@ -0,0 +1,216 @@ +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 3 +#define BOOST_TEST_MODULE Boost.Threads: thread launching test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> +#include <string> +#include <vector> + +bool normal_function_called=false; + +void normal_function() +{ + normal_function_called=true; +} + +BOOST_AUTO_TEST_CASE(test_thread_function_no_arguments) +{ + boost::thread function(&normal_function); + function.join(); + BOOST_CHECK(normal_function_called); +} + +int nfoa_res=0; + +void normal_function_one_arg(int i) +{ + nfoa_res=i; +} + +BOOST_AUTO_TEST_CASE(test_thread_function_one_argument) +{ + boost::thread function(&normal_function_one_arg,42); + function.join(); + BOOST_CHECK_EQUAL(42,nfoa_res); +} + +struct callable_no_args +{ + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_no_args::called=false; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_no_arguments) +{ + callable_no_args func; + boost::thread callable(func); + callable.join(); + BOOST_CHECK(callable_no_args::called); +} + +struct callable_noncopyable_no_args: + boost::noncopyable +{ + callable_noncopyable_no_args() : boost::noncopyable() {} + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_noncopyable_no_args::called=false; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_ref_no_arguments) +{ + callable_noncopyable_no_args func; + + boost::thread callable(boost::ref(func)); + callable.join(); + BOOST_CHECK(callable_noncopyable_no_args::called); +} + +struct callable_one_arg +{ + static bool called; + static int called_arg; + + void operator()(int arg) const + { + called=true; + called_arg=arg; + } +}; + +bool callable_one_arg::called=false; +int callable_one_arg::called_arg=0; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_one_argument) +{ + callable_one_arg func; + boost::thread callable(func,42); + callable.join(); + BOOST_CHECK(callable_one_arg::called); + BOOST_CHECK_EQUAL(callable_one_arg::called_arg,42); +} + +struct callable_multiple_arg +{ + static bool called_two; + static int called_two_arg1; + static double called_two_arg2; + static bool called_three; + static std::string called_three_arg1; + static std::vector<int> called_three_arg2; + static int called_three_arg3; + + void operator()(int arg1,double arg2) const + { + called_two=true; + called_two_arg1=arg1; + called_two_arg2=arg2; + } + void operator()(std::string const& arg1,std::vector<int> const& arg2,int arg3) const + { + called_three=true; + called_three_arg1=arg1; + called_three_arg2=arg2; + called_three_arg3=arg3; + } +}; + +bool callable_multiple_arg::called_two=false; +bool callable_multiple_arg::called_three=false; +int callable_multiple_arg::called_two_arg1; +double callable_multiple_arg::called_two_arg2; +std::string callable_multiple_arg::called_three_arg1; +std::vector<int> callable_multiple_arg::called_three_arg2; +int callable_multiple_arg::called_three_arg3; + +BOOST_AUTO_TEST_CASE(test_thread_callable_object_multiple_arguments) +{ + std::vector<int> x; + for(unsigned i=0;i<7;++i) + { + x.push_back(i*i); + } + + callable_multiple_arg func; + // Avoid + // boost/bind/bind.hpp(392) : warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data + + boost::thread callable3(func,"hello",x,1); + callable3.join(); + BOOST_CHECK(callable_multiple_arg::called_three); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg1,"hello"); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg2.size(),x.size()); + for(unsigned j=0;j<x.size();++j) + { + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg2.at(j),x[j]); + } + + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg3,1); + + double const dbl=1.234; + + boost::thread callable2(func,19,dbl); + callable2.join(); + BOOST_CHECK(callable_multiple_arg::called_two); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_two_arg1,19); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_two_arg2,dbl); +} + +struct X +{ + bool function_called; + int arg_value; + + X(): + function_called(false), + arg_value(0) + {} + + + void f0() + { + function_called=true; + } + + void f1(int i) + { + arg_value=i; + } + +}; + +BOOST_AUTO_TEST_CASE(test_thread_member_function_no_arguments) +{ + X x; + + boost::thread function(&X::f0,&x); + function.join(); + BOOST_CHECK(x.function_called); +} + + +BOOST_AUTO_TEST_CASE(test_thread_member_function_one_argument) +{ + X x; + boost::thread function(&X::f1,&x,42); + function.join(); + BOOST_CHECK_EQUAL(42,x.arg_value); +} diff --git a/src/boost/libs/thread/test/test_thread_mf.cpp b/src/boost/libs/thread/test/test_thread_mf.cpp new file mode 100644 index 000000000..843008fa7 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_mf.cpp @@ -0,0 +1,135 @@ +// +// Copyright (C) 2008 Peter Dimov +// +// 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 <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct X +{ + mutable unsigned int hash; + + X(): hash(0) {} + + int f0() { f1(17); return 0; } + int g0() const { g1(17); return 0; } + + int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; } + int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; } + + int f2(int a1, int a2) { f1(a1); f1(a2); return 0; } + int g2(int a1, int a2) const { g1(a1); g1(a2); return 0; } + + int f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; } + int g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; } + + int f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; } + int g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; } + + int f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; } + int g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; } + + int f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; } + int g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; } + + int f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; } + int g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; } + + int f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; } + int g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; } +}; + +int main() +{ + X x; + + // 0 + + boost::thread( &X::f0, &x ).join(); + boost::thread( &X::f0, boost::ref(x) ).join(); + + boost::thread( &X::g0, &x ).join(); + boost::thread( &X::g0, x ).join(); + boost::thread( &X::g0, boost::ref(x) ).join(); + + // 1 + + boost::thread( &X::f1, &x, 1 ).join(); + boost::thread( &X::f1, boost::ref(x), 1 ).join(); + + boost::thread( &X::g1, &x, 1 ).join(); + boost::thread( &X::g1, x, 1 ).join(); + boost::thread( &X::g1, boost::ref(x), 1 ).join(); + + // 2 + + boost::thread( &X::f2, &x, 1, 2 ).join(); + boost::thread( &X::f2, boost::ref(x), 1, 2 ).join(); + + boost::thread( &X::g2, &x, 1, 2 ).join(); + boost::thread( &X::g2, x, 1, 2 ).join(); + boost::thread( &X::g2, boost::ref(x), 1, 2 ).join(); + + // 3 + + boost::thread( &X::f3, &x, 1, 2, 3 ).join(); + boost::thread( &X::f3, boost::ref(x), 1, 2, 3 ).join(); + + boost::thread( &X::g3, &x, 1, 2, 3 ).join(); + boost::thread( &X::g3, x, 1, 2, 3 ).join(); + boost::thread( &X::g3, boost::ref(x), 1, 2, 3 ).join(); + + // 4 + + boost::thread( &X::f4, &x, 1, 2, 3, 4 ).join(); + boost::thread( &X::f4, boost::ref(x), 1, 2, 3, 4 ).join(); + + boost::thread( &X::g4, &x, 1, 2, 3, 4 ).join(); + boost::thread( &X::g4, x, 1, 2, 3, 4 ).join(); + boost::thread( &X::g4, boost::ref(x), 1, 2, 3, 4 ).join(); + + // 5 + + boost::thread( &X::f5, &x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::f5, boost::ref(x), 1, 2, 3, 4, 5 ).join(); + + boost::thread( &X::g5, &x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::g5, x, 1, 2, 3, 4, 5 ).join(); + boost::thread( &X::g5, boost::ref(x), 1, 2, 3, 4, 5 ).join(); + + // 6 + + boost::thread( &X::f6, &x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::f6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join(); + + boost::thread( &X::g6, &x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::g6, x, 1, 2, 3, 4, 5, 6 ).join(); + boost::thread( &X::g6, boost::ref(x), 1, 2, 3, 4, 5, 6 ).join(); + + // 7 + + boost::thread( &X::f7, &x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::f7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join(); + + boost::thread( &X::g7, &x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::g7, x, 1, 2, 3, 4, 5, 6, 7).join(); + boost::thread( &X::g7, boost::ref(x), 1, 2, 3, 4, 5, 6, 7).join(); + + // 8 + + boost::thread( &X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::f8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + + boost::thread( &X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + boost::thread( &X::g8, boost::ref(x), 1, 2, 3, 4, 5, 6, 7, 8 ).join(); + + BOOST_TEST( x.hash == 23558 ); + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/test_thread_move.cpp b/src/boost/libs/thread/test/test_thread_move.cpp new file mode 100644 index 000000000..e86db8cad --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_move.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2007-9 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE Boost.Threads: thread move test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +BOOST_AUTO_TEST_CASE(test_move_on_construction) +{ + boost::thread::id the_id; + boost::thread x=boost::thread(do_nothing,&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + +boost::thread make_thread(boost::thread::id* the_id) +{ + return boost::thread(do_nothing,the_id); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_return) +{ + boost::thread::id the_id; + boost::thread x=make_thread(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + +BOOST_AUTO_TEST_CASE(test_move_assign) +{ + boost::thread::id the_id; + boost::thread x(do_nothing,&the_id); + boost::thread y; + y=boost::move(x); + boost::thread::id y_id=y.get_id(); + y.join(); + BOOST_CHECK_EQUAL(the_id,y_id); +} + + diff --git a/src/boost/libs/thread/test/test_thread_move_return.cpp b/src/boost/libs/thread/test/test_thread_move_return.cpp new file mode 100644 index 000000000..f714fb0a5 --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_move_return.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE +#define BOOST_TEST_MODULE Boost.Threads: thread move return test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +boost::thread make_thread_move_return(boost::thread::id* the_id) +{ + boost::thread t(do_nothing,the_id); + return boost::move(t); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_move_return) +{ + boost::thread::id the_id; + boost::thread x=make_thread_move_return(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} + diff --git a/src/boost/libs/thread/test/test_thread_return_local.cpp b/src/boost/libs/thread/test/test_thread_return_local.cpp new file mode 100644 index 000000000..6ffd1083a --- /dev/null +++ b/src/boost/libs/thread/test/test_thread_return_local.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2009 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_USES_MOVE + +#define BOOST_TEST_MODULE Boost.Threads: thread return local test suite + +#include <boost/thread/thread_only.hpp> +#include <boost/test/unit_test.hpp> + +void do_nothing(boost::thread::id* my_id) +{ + *my_id=boost::this_thread::get_id(); +} + +boost::thread make_thread_return_local(boost::thread::id* the_id) +{ + boost::thread t(do_nothing,the_id); + return boost::move(t); +} + +BOOST_AUTO_TEST_CASE(test_move_from_function_return_local) +{ + boost::thread::id the_id; + boost::thread x=make_thread_return_local(&the_id); + boost::thread::id x_id=x.get_id(); + x.join(); + BOOST_CHECK_EQUAL(the_id,x_id); +} diff --git a/src/boost/libs/thread/test/test_time_jumps.cpp b/src/boost/libs/thread/test/test_time_jumps.cpp new file mode 100644 index 000000000..706bafa47 --- /dev/null +++ b/src/boost/libs/thread/test/test_time_jumps.cpp @@ -0,0 +1,2398 @@ +#ifdef _WIN32 + #include <windows.h> +#else + #include <sys/time.h> +#endif + +#include "boost/bind/bind.hpp" +#include "boost/chrono.hpp" +#include "boost/chrono/ceil.hpp" +#include "boost/date_time.hpp" +#include "boost/thread/concurrent_queues/sync_priority_queue.hpp" +#include "boost/thread/concurrent_queues/sync_timed_queue.hpp" +#include "boost/thread/future.hpp" +#include "boost/thread/mutex.hpp" +#include "boost/thread/recursive_mutex.hpp" +#include "boost/thread/shared_lock_guard.hpp" +#include "boost/thread/shared_mutex.hpp" +#include "boost/thread/thread.hpp" + +#include <iomanip> +#ifdef TEST_CPP14_FEATURES +#include <future> +#include <mutex> +#include <shared_mutex> +#include <thread> +#endif + +/******************************************************************************/ + +/* + * Summary: + * + * This code tests the behavior of time-related functions in the presence of + * system clock changes (jumps). It requires root/Administrator privileges in + * order to run because it changes the system clock. NTP should also be disabled + * while running this code so that NTP can't change the system clock. + * + * Each function to be tested is executed five times. The amount of time the + * function waits before returning is measured against the amount of time the + * function was expected to wait. If the difference exceeds a threshold value + * (defined below) then the test fails. + * + * The following values are intentially: + * - more than 200 milliseconds + * - more than 200 milliseconds apart + * - not a multiple of 100 milliseconds + * - not a multiple of each other + * - don't sum or diff to a multiple of 100 milliseconds + */ +const long long s_waitMs = 580; +const long long s_shortJumpMs = 230; +const long long s_longJumpMs = 870; // Causes additional, unavoidable failures when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is disabled +const long long s_sleepBeforeJumpMs = 110; + +#ifdef _WIN32 +const long long s_maxEarlyErrorMs = 10 + + 100; // Windows is unpredictable, especially in a VM, so allow extra time if the function returns early +const long long s_maxLateErrorMs = 110 // due to polling, functions may not return for up to 100 milliseconds after they are supposed to + + 100; // Windows is slow, especially in a VM, so allow extra time for the functions to return +#else +const long long s_maxEarlyErrorMs = 10; +const long long s_maxLateErrorMs = 110; // Due to polling, functions may not return for up to 100 milliseconds after they are supposed to +#endif + +int g_numTestsRun = 0; +int g_numTestsPassed = 0; +int g_numTestsFailed = 0; + +/******************************************************************************/ + +// A custom clock based off the system clock but with a different epoch. + +namespace custom +{ + class custom_boost_clock + { + public: + typedef boost::chrono::microseconds duration; // intentionally not nanoseconds + typedef duration::rep rep; + typedef duration::period period; + typedef boost::chrono::time_point<custom_boost_clock> time_point; + static bool is_steady; + + static time_point now(); + }; + + bool custom_boost_clock::is_steady = false; + + custom_boost_clock::time_point custom_boost_clock::now() + { + return time_point(boost::chrono::ceil<duration>(boost::chrono::system_clock::now().time_since_epoch()) - boost::chrono::hours(10 * 365 * 24)); + } + +#ifdef TEST_CPP14_FEATURES + class custom_std_clock + { + public: + typedef std::chrono::microseconds duration; // intentionally not nanoseconds + typedef duration::rep rep; + typedef duration::period period; + typedef std::chrono::time_point<custom_std_clock> time_point; + static bool is_steady; + + static time_point now(); + }; + + bool custom_std_clock::is_steady = false; + + custom_std_clock::time_point custom_std_clock::now() + { + return time_point(std::chrono::duration_cast<duration>(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24)); + } +#endif +} + +/******************************************************************************/ + +template <typename MutexType = boost::mutex, typename CondType = boost::condition_variable> +struct BoostHelper +{ + typedef MutexType mutex; + typedef CondType cond; + + typedef boost::lock_guard<MutexType> lock_guard; + typedef boost::unique_lock<MutexType> unique_lock; + + typedef boost::chrono::milliseconds milliseconds; + typedef boost::chrono::nanoseconds nanoseconds; + + typedef boost::chrono::system_clock system_clock; + typedef boost::chrono::steady_clock steady_clock; + typedef custom::custom_boost_clock custom_clock; + + typedef system_clock::time_point system_time_point; + typedef steady_clock::time_point steady_time_point; + typedef custom_clock::time_point custom_time_point; + + typedef boost::cv_status cv_status; + typedef boost::future_status future_status; + + typedef boost::packaged_task<bool> packaged_task; + typedef boost::future<bool> future; + typedef boost::shared_future<bool> shared_future; + + typedef boost::thread thread; + + static const milliseconds waitDur; + + template <typename T> + static void sleep_for(T d) + { + boost::this_thread::sleep_for(d); + } + + template <typename T> + static void sleep_for_no_int(T d) + { + boost::this_thread::no_interruption_point::sleep_for(d); + } + + template <typename T> + static void sleep_until(T t) + { + boost::this_thread::sleep_until(t); + } + + template <typename T> + static void sleep_until_no_int(T t) + { + boost::this_thread::no_interruption_point::sleep_until(t); + } + + static system_time_point systemNow() + { + return system_clock::now(); + } + + static steady_time_point steadyNow() + { + return steady_clock::now(); + } + + static custom_time_point customNow() + { + return custom_clock::now(); + } + + template <class ToDuration, class Rep, class Period> + static ToDuration duration_cast(const boost::chrono::duration<Rep, Period>& d) + { + return boost::chrono::duration_cast<ToDuration>(d); + } + + static milliseconds zero() + { + return milliseconds(0); + } +}; + +template <typename MutexType, typename CondType> +const typename BoostHelper<MutexType, CondType>::milliseconds +BoostHelper<MutexType, CondType>::waitDur = typename BoostHelper<MutexType, CondType>::milliseconds(s_waitMs); + +#ifdef TEST_CPP14_FEATURES +template <typename MutexType = std::mutex, typename CondType = std::condition_variable> +struct StdHelper +{ + typedef MutexType mutex; + typedef CondType cond; + + typedef std::lock_guard<MutexType> lock_guard; + typedef std::unique_lock<MutexType> unique_lock; + + typedef std::chrono::milliseconds milliseconds; + typedef std::chrono::nanoseconds nanoseconds; + + typedef std::chrono::system_clock system_clock; + typedef std::chrono::steady_clock steady_clock; + typedef custom::custom_std_clock custom_clock; + + typedef system_clock::time_point system_time_point; + typedef steady_clock::time_point steady_time_point; + typedef custom_clock::time_point custom_time_point; + + typedef std::cv_status cv_status; + typedef std::future_status future_status; + + typedef std::packaged_task<bool()> packaged_task; + typedef std::future<bool> future; + typedef std::shared_future<bool> shared_future; + + typedef std::thread thread; + + static const milliseconds waitDur; + + template <typename T> + static void sleep_for(T d) + { + std::this_thread::sleep_for(d); + } + + template <typename T> + static void sleep_until(T t) + { + std::this_thread::sleep_until(t); + } + + static system_time_point systemNow() + { + return system_clock::now(); + } + + static steady_time_point steadyNow() + { + return steady_clock::now(); + } + + static custom_time_point customNow() + { + return custom_clock::now(); + } + + template <class ToDuration, class Rep, class Period> + static ToDuration duration_cast(const std::chrono::duration<Rep, Period>& d) + { + return std::chrono::duration_cast<ToDuration>(d); + } + + static milliseconds zero() + { + return milliseconds(0); + } +}; + +template <typename MutexType, typename CondType> +const typename StdHelper<MutexType, CondType>::milliseconds +StdHelper<MutexType, CondType>::waitDur = typename StdHelper<MutexType, CondType>::milliseconds(s_waitMs); +#endif + +/******************************************************************************/ + +#ifdef _WIN32 + +void changeSystemTime(long long changeMs) +{ + Sleep(s_sleepBeforeJumpMs); + + SYSTEMTIME systemTime; + GetSystemTime(&systemTime); + + FILETIME fileTime; + if (!SystemTimeToFileTime(&systemTime, &fileTime)) + { + std::cout << "ERROR: Couldn't convert system time to file time" << std::endl; + } + + ULARGE_INTEGER largeInt; + largeInt.LowPart = fileTime.dwLowDateTime; + largeInt.HighPart = fileTime.dwHighDateTime; + largeInt.QuadPart += changeMs * 10000; + fileTime.dwLowDateTime = largeInt.LowPart; + fileTime.dwHighDateTime = largeInt.HighPart; + + if (!FileTimeToSystemTime(&fileTime, &systemTime)) + { + std::cout << "ERROR: Couldn't convert file time to system time" << std::endl; + } + + if (!SetSystemTime(&systemTime)) + { + std::cout << "ERROR: Couldn't set system time" << std::endl; + } +} + +#else + +void changeSystemTime(long long changeMs) +{ + struct timespec sleepTs; + sleepTs.tv_sec = (s_sleepBeforeJumpMs / 1000); + sleepTs.tv_nsec = (s_sleepBeforeJumpMs % 1000) * 1000000; + nanosleep(&sleepTs, NULL); + + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) + { + std::cout << "ERROR: Couldn't get system time" << std::endl; + } + + changeMs += tv.tv_sec * 1000; + changeMs += tv.tv_usec / 1000; + tv.tv_sec = (changeMs / 1000); + tv.tv_usec = (changeMs % 1000) * 1000; + + if (settimeofday(&tv, NULL) != 0) + { + std::cout << "ERROR: Couldn't set system time" << std::endl; + } +} + +#endif + +enum RcEnum +{ + e_no_timeout, + e_timeout, + e_failed_bad, + e_failed_good, + e_succeeded_bad, + e_succeeded_good, + e_ready_bad, + e_not_ready_good, + e_na +}; + +template <typename Helper> +void checkWaitTime(typename Helper::nanoseconds expected, typename Helper::nanoseconds actual, RcEnum rc) +{ + if (expected != Helper::zero() && expected < typename Helper::milliseconds(s_sleepBeforeJumpMs)) + { + expected = typename Helper::milliseconds(s_sleepBeforeJumpMs); + } + + typename Helper::milliseconds expectedMs = Helper::template duration_cast<typename Helper::milliseconds>(expected); + typename Helper::milliseconds actualMs = Helper::template duration_cast<typename Helper::milliseconds>(actual); + + std::cout << "Expected: " << std::setw(4) << expectedMs.count() << " ms" + << ", Actual: " << std::setw(4) << actualMs.count() << " ms" + << ", Returned: "; + switch (rc) + { + case e_no_timeout : std::cout << "no_timeout, "; break; + case e_timeout : std::cout << "timeout, "; break; + case e_failed_bad : std::cout << "failed, "; break; + case e_failed_good : std::cout << "failed, "; break; + case e_succeeded_bad : std::cout << "succeeded, "; break; + case e_succeeded_good : std::cout << "succeeded, "; break; + case e_ready_bad : std::cout << "ready, "; break; + case e_not_ready_good : std::cout << "not_ready, "; break; + default : std::cout << "N/A, "; break; + } + + if (expectedMs == Helper::zero()) + { + std::cout << "FAILED: SKIPPED (test would lock up if run)"; + g_numTestsFailed++; + } + else if (actual < expected - typename Helper::milliseconds(s_maxEarlyErrorMs)) + { + std::cout << "FAILED: TOO SHORT"; + if (rc == e_timeout) // bad + { + std::cout << ", RETURNED TIMEOUT"; + } + else if (rc == e_failed_bad) + { + std::cout << ", RETURNED FAILED"; + } + else if (rc == e_succeeded_bad) + { + std::cout << ", RETURNED SUCCEEDED"; + } + else if (rc == e_ready_bad) + { + std::cout << ", RETURNED READY"; + } + g_numTestsFailed++; + } + else if (actual > expected + typename Helper::milliseconds(s_maxLateErrorMs)) + { + std::cout << "FAILED: TOO LONG"; + if (rc == e_no_timeout) // bad + { + std::cout << ", RETURNED NO_TIMEOUT"; + } + else if (rc == e_failed_bad) + { + std::cout << ", RETURNED FAILED"; + } + else if (rc == e_succeeded_bad) + { + std::cout << ", RETURNED SUCCEEDED"; + } + else if (rc == e_ready_bad) + { + std::cout << ", RETURNED READY"; + } + g_numTestsFailed++; + } + else if (rc == e_no_timeout) // bad + { + std::cout << "FAILED: RETURNED NO_TIMEOUT"; + g_numTestsFailed++; + } + else if (rc == e_failed_bad) + { + std::cout << "FAILED: RETURNED FAILED"; + g_numTestsFailed++; + } + else if (rc == e_succeeded_bad) + { + std::cout << "FAILED: RETURNED SUCCEEDED"; + g_numTestsFailed++; + } + else if (rc == e_ready_bad) + { + std::cout << "FAILED: RETURNED READY"; + g_numTestsFailed++; + } + else + { + std::cout << "Passed"; + g_numTestsPassed++; + } + std::cout << std::endl; + + g_numTestsRun++; +} + +void sleepForLongTime() +{ +#ifdef _WIN32 + Sleep(10000); +#else + struct timespec ts = {5, 0}; + nanosleep(&ts, NULL); +#endif +} + +bool returnFalse() +{ + return false; +} + +/******************************************************************************/ + +// Run the test in the context provided, which may be the current thread or a separate thread. +template <typename Helper, typename Context, typename Function> +void runTestInContext(Context context, Function func, const std::string name) +{ + std::cout << name << ":" << std::endl; + + { + std::cout << " While system clock remains stable: "; + context(func, 0); + } + + { + std::cout << " While system clock jumps back (short): "; + typename Helper::thread t(boost::bind(changeSystemTime, -s_shortJumpMs)); + context(func, -s_shortJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps back (long): "; + typename Helper::thread t(boost::bind(changeSystemTime, -s_longJumpMs)); + context(func, -s_longJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps forward (short): "; + typename Helper::thread t(boost::bind(changeSystemTime, s_shortJumpMs)); + context(func, s_shortJumpMs); + t.join(); + } + + { + std::cout << " While system clock jumps forward (long): "; + typename Helper::thread t(boost::bind(changeSystemTime, s_longJumpMs)); + context(func, s_longJumpMs); + t.join(); + } +} + +//-------------------------------------- + +template <typename Helper, typename Function> +void noThreadContext(Function func, const long long jumpMs) +{ + func(jumpMs); +} + +template <typename Helper, typename Function> +void threadContextWithNone(Function func, const long long jumpMs) +{ + typename Helper::thread t(boost::bind(func, jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithUnique(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + typename Helper::lock_guard g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithShared(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + boost::shared_lock_guard<typename Helper::mutex> g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +template <typename Helper, typename Function> +void threadContextWithUpgrade(Function func, const long long jumpMs) +{ + typename Helper::mutex m; + boost::upgrade_lock<typename Helper::mutex> g(m); + typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); + t.join(); +} + +//-------------------------------------- + +// Run the test in the current thread. +template <typename Helper, typename Function> +void runTest(Function func, const std::string name) +{ + runTestInContext<Helper>(noThreadContext<Helper, Function>, func, name); +} + +// Run the test in a separate thread. +template <typename Helper, typename Function> +void runTestWithNone(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithNone<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass a locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithUnique(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithUnique<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass a shared-locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithShared(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithShared<Helper, Function>, func, name); +} + +// Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test. +template <typename Helper, typename Function> +void runTestWithUpgrade(Function func, const std::string name) +{ + runTestInContext<Helper>(threadContextWithUpgrade<Helper, Function>, func, name); +} + +/******************************************************************************/ + +// Test Sleep + +template <typename Helper> +void testSleepFor(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +template <typename Helper> +void testSleepUntilCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +//-------------------------------------- + +template <typename Helper> +void testSleepRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::sleep(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSleepAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::sleep(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testSleepStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for()"); + runTestWithNone<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), steady time"); + runTestWithNone<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), system time"); + runTestWithNone<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), custom time"); +} + +template <typename Helper> +void testSleepBoost(const std::string& name) +{ + testSleepStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), relative time"); + runTestWithNone<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), absolute time"); +} + +template <typename Helper> +void testSleepNoThreadStd(const std::string& name) +{ + std::cout << std::endl; + runTest<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for(), no thread"); + runTest<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), no thread, steady time"); + runTest<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), no thread, system time"); + runTest<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), no thread, custom time"); +} + +template <typename Helper> +void testSleepNoThreadBoost(const std::string& name) +{ + testSleepNoThreadStd<Helper>(name); + + // Boost-only functions + runTest<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), no thread, relative time"); + runTest<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), no thread, absolute time"); +} + +/******************************************************************************/ + +// Test Sleep, No Interruption Point + +template <typename Helper> +void testSleepForNoInt(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_for_no_int(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +template <typename Helper> +void testSleepUntilNoIntCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + Helper::sleep_until_no_int(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +} + +//-------------------------------------- + +#ifndef SKIP_NO_INT_SLEEP + +template <typename Helper> +void testSleepNoIntRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::no_interruption_point::sleep(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSleepNoIntAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + boost::this_thread::no_interruption_point::sleep(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +#endif + +//-------------------------------------- + +// Only Boost supports no_interruption_point + +template <typename Helper> +void testSleepNoIntBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for()"); + runTestWithNone<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), steady time"); + runTestWithNone<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), system time"); + runTestWithNone<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), custom time"); + +#ifndef SKIP_NO_INT_SLEEP + runTestWithNone<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), relative time"); + runTestWithNone<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), absolute time"); +#endif +} + +template <typename Helper> +void testSleepNoThreadNoIntBoost(const std::string& name) +{ + std::cout << std::endl; + runTest<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for(), no thread"); + runTest<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time"); + runTest<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time"); + runTest<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time"); + +#ifndef SKIP_NO_INT_SLEEP + runTest<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time"); + runTest<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time"); +#endif +} + +/******************************************************************************/ + +// Test Try Join + +template <typename Helper> +void testTryJoinFor(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilSteady(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilSystem(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryJoinUntilCustom(const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.try_join_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedJoinRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.timed_join(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedJoinAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + typename Helper::thread t3(sleepForLongTime); + bool succeeded = t3.timed_join(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +// Only Boost supports timed try_join functions + +template <typename Helper> +void testJoinBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testTryJoinFor <Helper>, name + "::thread::try_join_for()"); + runTestWithNone<Helper>(testTryJoinUntilSteady<Helper>, name + "::thread::try_join_until(), steady time"); + runTestWithNone<Helper>(testTryJoinUntilSystem<Helper>, name + "::thread::try_join_until(), system time"); + runTestWithNone<Helper>(testTryJoinUntilCustom<Helper>, name + "::thread::try_join_until(), custom time"); + runTestWithNone<Helper>(testTimedJoinRelative <Helper>, name + "::thread::timed_join(), relative time"); + runTestWithNone<Helper>(testTimedJoinAbsolute <Helper>, name + "::thread::timed_join(), absolute time"); +} + +/******************************************************************************/ + +// Test Condition Variable Wait + +template <typename Helper> +void testCondVarWaitFor(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_for(g, Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilSteady(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::steadyNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilSystem(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::systemNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilCustom(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = (cv.wait_until(g, Helper::customNow() + Helper::waitDur) == Helper::cv_status::no_timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testCondVarTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testCondVarWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testCondVarWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testCondVarWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testCondVarWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testCondVarBoost(const std::string& name) +{ + testCondVarStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testCondVarTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testCondVarTimedWaitAbsolute<Helper>, name + "::timed_wait(), absolute time"); +} + +/******************************************************************************/ + +// Test Condition Variable Wait with Predicate + +template <typename Helper> +void testCondVarWaitForPred(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_for(g, Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredSteady(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::steadyNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredSystem(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::systemNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +template <typename Helper> +void testCondVarWaitUntilPredCustom(const long long jumpMs) +{ + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool noTimeout = cv.wait_until(g, Helper::customNow() + Helper::waitDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarTimedWaitPredRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testCondVarTimedWaitPredAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::cond cv; + typename Helper::mutex m; + typename Helper::unique_lock g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testCondVarPredStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testCondVarWaitForPred <Helper>, name + "::wait_for(), with predicate"); + runTestWithNone<Helper>(testCondVarWaitUntilPredSteady<Helper>, name + "::wait_until(), with predicate, steady time"); + runTestWithNone<Helper>(testCondVarWaitUntilPredSystem<Helper>, name + "::wait_until(), with predicate, system time"); + runTestWithNone<Helper>(testCondVarWaitUntilPredCustom<Helper>, name + "::wait_until(), with predicate, custom time"); +} + +template <typename Helper> +void testCondVarPredBoost(const std::string& name) +{ + testCondVarPredStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testCondVarTimedWaitPredRelative<Helper>, name + "::timed_wait(), with predicate, relative time"); + runTestWithNone<Helper>(testCondVarTimedWaitPredAbsolute<Helper>, name + "::timed_wait(), with predicate, absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock + +template <typename Helper> +void testTryLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testMutexStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockFor <Helper>, name + "::try_lock_for()"); + runTestWithUnique<Helper>(testTryLockUntilSteady<Helper>, name + "::try_lock_until(), steady time"); + runTestWithUnique<Helper>(testTryLockUntilSystem<Helper>, name + "::try_lock_until(), system time"); + runTestWithUnique<Helper>(testTryLockUntilCustom<Helper>, name + "::try_lock_until(), custom time"); +} + +template <typename Helper> +void testMutexBoost(const std::string& name) +{ + testMutexStd<Helper>(name); + + // Boost-only functions + runTestWithUnique<Helper>(testTimedLockRelative<Helper>, name + "::timed_lock(), relative time"); + runTestWithUnique<Helper>(testTimedLockAbsolute<Helper>, name + "::timed_lock(), absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock Shared + +template <typename Helper> +void testTryLockSharedFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockSharedUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_shared_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockSharedRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_shared(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockSharedAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_shared(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testMutexSharedStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockSharedFor <Helper>, name + "::try_lock_shared_for()"); + runTestWithUnique<Helper>(testTryLockSharedUntilSteady<Helper>, name + "::try_lock_shared_until(), steady time"); + runTestWithUnique<Helper>(testTryLockSharedUntilSystem<Helper>, name + "::try_lock_shared_until(), system time"); + runTestWithUnique<Helper>(testTryLockSharedUntilCustom<Helper>, name + "::try_lock_shared_until(), custom time"); +} + +template <typename Helper> +void testMutexSharedBoost(const std::string& name) +{ + testMutexSharedStd<Helper>(name); + + // Boost-only functions + runTestWithUnique<Helper>(testTimedLockSharedRelative<Helper>, name + "::timed_lock_shared(), relative time"); + runTestWithUnique<Helper>(testTimedLockSharedAbsolute<Helper>, name + "::timed_lock_shared(), absolute time"); +} + +/******************************************************************************/ + +// Test Try Lock Upgrade + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + +template <typename Helper> +void testTryLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_lock_upgrade_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTimedLockUpgradeRelative(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_upgrade(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testTimedLockUpgradeAbsolute(typename Helper::mutex& m, const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool succeeded = m.timed_lock_upgrade(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::upgrade_lock<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +//-------------------------------------- + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_for(Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +template <typename Helper> +void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) +{ + boost::shared_lock_guard<typename Helper::mutex> g(m); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::customNow() + Helper::waitDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); +} + +#endif + +//-------------------------------------- + +// Only Boost supports upgrade mutexes + +template <typename Helper> +void testMutexUpgradeBoost(const std::string& name) +{ +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + std::cout << std::endl; + runTestWithUnique<Helper>(testTryLockUpgradeFor <Helper>, name + "::try_lock_upgrade_for()"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilSteady<Helper>, name + "::try_lock_upgrade_until(), steady time"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilSystem<Helper>, name + "::try_lock_upgrade_until(), system time"); + runTestWithUnique<Helper>(testTryLockUpgradeUntilCustom<Helper>, name + "::try_lock_upgrade_until(), custom time"); + runTestWithUnique<Helper>(testTimedLockUpgradeRelative <Helper>, name + "::timed_lock_upgrade(), relative time"); + runTestWithUnique<Helper>(testTimedLockUpgradeAbsolute <Helper>, name + "::timed_lock_upgrade(), absolute time"); + + std::cout << std::endl; + runTestWithShared<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_for()"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_until(), steady time"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_until(), system time"); + runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_until(), custom time"); + + std::cout << std::endl; + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockFor <Helper>, name + "::try_unlock_upgrade_and_lock_for()"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSteady<Helper>, name + "::try_unlock_upgrade_and_lock_until(), steady time"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSystem<Helper>, name + "::try_unlock_upgrade_and_lock_until(), system time"); + runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilCustom<Helper>, name + "::try_unlock_upgrade_and_lock_until(), custom time"); + + std::cout << std::endl; + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_upgrade_for()"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), system time"); + runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time"); +#endif +} + +/******************************************************************************/ + +// Test Future Wait + +template <typename Helper> +void testFutureWaitFor(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_for(Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilSteady(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilSystem(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testFutureWaitUntilCustom(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (f.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testFutureTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = f.timed_wait(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testFutureTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = f.timed_wait_until(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testFutureStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testFutureWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testFutureBoost(const std::string& name) +{ + testFutureStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); +} + +/******************************************************************************/ + +// Test Shared Future Wait + +template <typename Helper> +void testSharedFutureWaitFor(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_for(Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilSteady(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilSystem(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSharedFutureWaitUntilCustom(const long long jumpMs) +{ + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (sf.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testSharedFutureTimedWaitRelative(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = sf.timed_wait(ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +template <typename Helper> +void testSharedFutureTimedWaitAbsolute(const long long jumpMs) +{ +#ifndef SKIP_DATETIME_FUNCTIONS + typename Helper::packaged_task pt(returnFalse); + typename Helper::future f = pt.get_future(); + typename Helper::shared_future sf = boost::move(f); + + typename Helper::steady_time_point before(Helper::steadyNow()); + boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); + boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count()); + bool noTimeout = sf.timed_wait_until(ptNow + ptDur); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); +#else + checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); +#endif +} + +//-------------------------------------- + +template <typename Helper> +void testSharedFutureStd(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSharedFutureWaitFor <Helper>, name + "::wait_for()"); + runTestWithNone<Helper>(testSharedFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); + runTestWithNone<Helper>(testSharedFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); + runTestWithNone<Helper>(testSharedFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); +} + +template <typename Helper> +void testSharedFutureBoost(const std::string& name) +{ + testSharedFutureStd<Helper>(name); + + // Boost-only functions + runTestWithNone<Helper>(testSharedFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); + runTestWithNone<Helper>(testSharedFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); +} + +/******************************************************************************/ + +// Test Sync Priority Queue + +template <typename Helper> +void testSyncPriorityQueuePullFor(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilSteady(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilSystem(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncPriorityQueuePullUntilCustom(const long long jumpMs) +{ + boost::sync_priority_queue<int> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +// Only Boost supports sync_priority_queue + +template <typename Helper> +void testSyncPriorityQueueBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSyncPriorityQueuePullFor <Helper>, name + "::pull_for()"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSteady<Helper>, name + "::pull_until(), steady time"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSystem<Helper>, name + "::pull_until(), system time"); + runTestWithNone<Helper>(testSyncPriorityQueuePullUntilCustom<Helper>, name + "::pull_until(), custom time"); +} + +/******************************************************************************/ + +// Test Sync Timed Queue + +template <typename Helper> +void testSyncTimedQueuePullForEmptySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullForEmptySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, typename Helper::milliseconds(10000)); // a long time + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool notReady = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::steadyNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::steadyNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::systemNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::systemNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::customNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.pull_until(Helper::customNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +//-------------------------------------- + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::steady_clock> q; + q.push(0, Helper::steadyNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::system_clock> q; + q.push(0, Helper::systemNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +template <typename Helper> +void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs) +{ + boost::sync_timed_queue<int, typename Helper::custom_clock> q; + q.push(0, Helper::customNow() + Helper::waitDur); + int i; + + typename Helper::steady_time_point before(Helper::steadyNow()); + bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); + typename Helper::steady_time_point after(Helper::steadyNow()); + + checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); +} + +//-------------------------------------- + +// Only Boost supports sync_timed_queue + +template <typename Helper> +void testSyncTimedQueueBoost(const std::string& name) +{ + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySteady <Helper>, name + "::pull_for(), empty, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySystem <Helper>, name + "::pull_for(), empty, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForEmptyCustom <Helper>, name + "::pull_for(), empty, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySteady<Helper>, name + "::pull_until(), empty, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySystem<Helper>, name + "::pull_until(), empty, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptyCustom<Helper>, name + "::pull_until(), empty, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySteady <Helper>, name + "::pull_for(), not ready, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySystem <Helper>, name + "::pull_for(), not ready, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadyCustom <Helper>, name + "::pull_for(), not ready, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySteady<Helper>, name + "::pull_until(), not ready, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySystem<Helper>, name + "::pull_until(), not ready, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadyCustom<Helper>, name + "::pull_until(), not ready, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSteady <Helper>, name + "::pull_for(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSystem <Helper>, name + "::pull_for(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsCustom <Helper>, name + "::pull_for(), succeeds, custom time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSteady<Helper>, name + "::pull_until(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSystem<Helper>, name + "::pull_until(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsCustom<Helper>, name + "::pull_until(), succeeds, custom time"); + + std::cout << std::endl; + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSteady<Helper>, name + "::wait_pull(), succeeds, steady time"); + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSystem<Helper>, name + "::wait_pull(), succeeds, system time"); + runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsCustom<Helper>, name + "::wait_pull(), succeeds, custom time"); +} + +/******************************************************************************/ + +int main() +{ + std::cout << std::endl; + std::cout << "INFO: This test requires root/Administrator privileges in order to change the system clock." << std::endl; + std::cout << "INFO: Disable NTP while running this test to prevent NTP from changing the system clock." << std::endl; + std::cout << std::endl; + + std::cout << "BOOST_HAS_PTHREAD_DELAY_NP: "; +#ifdef BOOST_HAS_PTHREAD_DELAY_NP + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_HAS_NANOSLEEP: "; +#ifdef BOOST_HAS_NANOSLEEP + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_SLEEP_FOR_IS_STEADY: "; +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "CLOCK_MONOTONIC: "; +#ifdef CLOCK_MONOTONIC + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN: "; +#ifdef BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS: "; +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_V2_SHARED_MUTEX: "; +#ifdef BOOST_THREAD_V2_SHARED_MUTEX + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << "BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC: "; +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + std::cout << "YES" << std::endl; +#else + std::cout << "NO" << std::endl; +#endif + + std::cout << std::endl; + std::cout << "Wait Time: " << s_waitMs << " ms" << std::endl; + std::cout << "Short Jump Time: " << s_shortJumpMs << " ms" << std::endl; + std::cout << "Long Jump Time: " << s_longJumpMs << " ms" << std::endl; + std::cout << "Sleep Before Jump Time: " << s_sleepBeforeJumpMs << " ms" << std::endl; + std::cout << "Max Early Error: " << s_maxEarlyErrorMs << " ms" << std::endl; + std::cout << "Max Late Error: " << s_maxLateErrorMs << " ms" << std::endl; + + testSleepBoost <BoostHelper< > >("boost"); + testSleepNoIntBoost <BoostHelper< > >("boost"); + testSleepNoThreadBoost <BoostHelper< > >("boost"); + testSleepNoThreadNoIntBoost<BoostHelper< > >("boost"); + testJoinBoost <BoostHelper< > >("boost"); + testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); + testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); + testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); + testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); + testMutexBoost <BoostHelper<boost::timed_mutex > >("boost::timed_mutex"); + testMutexBoost <BoostHelper<boost::recursive_timed_mutex > >("boost::recursive_timed_mutex"); + testMutexBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testMutexSharedBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testMutexUpgradeBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex + testFutureBoost <BoostHelper< > >("boost::future"); + testSharedFutureBoost <BoostHelper< > >("boost::shared_future"); + testSyncPriorityQueueBoost <BoostHelper< > >("boost::sync_priority_queue"); + testSyncTimedQueueBoost <BoostHelper< > >("boost::sync_timed_queue"); + +#ifdef TEST_CPP14_FEATURES + testSleepStd <StdHelper< > >("std"); + testSleepNoThreadStd<StdHelper< > >("std"); + testCondVarStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); + testCondVarPredStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); + testCondVarStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); + testCondVarPredStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); + testMutexStd <StdHelper<std::timed_mutex > >("std::timed_mutex"); + testMutexStd <StdHelper<std::recursive_timed_mutex > >("std::recursive_timed_mutex"); + testMutexStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); + testMutexSharedStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); + testFutureStd <StdHelper< > >("std::future"); + testSharedFutureStd <StdHelper< > >("std::shared_future"); +#endif + + std::cout << std::endl; + std::cout << "Number of Tests Run: " << g_numTestsRun << std::endl; + std::cout << "Number of Tests Passed: " << g_numTestsPassed << std::endl; + std::cout << "Number of Tests Failed: " << g_numTestsFailed << std::endl; + + return 0; +} diff --git a/src/boost/libs/thread/test/test_tss.cpp b/src/boost/libs/thread/test/test_tss.cpp new file mode 100644 index 000000000..08bbddc0c --- /dev/null +++ b/src/boost/libs/thread/test/test_tss.cpp @@ -0,0 +1,511 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#define BOOST_TEST_MODULE Boost.Threads: tss test suite + +#include <boost/thread/detail/config.hpp> +#include <boost/predef/platform.h> + +#include <boost/thread/tss.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> + +#include <boost/test/unit_test.hpp> + +#include "./util.inl" + +#include <iostream> + +#if defined(BOOST_THREAD_PLATFORM_WIN32) + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#endif + +boost::mutex check_mutex; +boost::mutex tss_mutex; +int tss_instances = 0; +int tss_total = 0; + +struct tss_value_t +{ + tss_value_t() + { + boost::unique_lock<boost::mutex> lock(tss_mutex); + ++tss_instances; + ++tss_total; + value = 0; + } + ~tss_value_t() + { + boost::unique_lock<boost::mutex> lock(tss_mutex); + --tss_instances; + } + int value; +}; + +boost::thread_specific_ptr<tss_value_t> tss_value; + +void test_tss_thread() +{ + tss_value.reset(new tss_value_t()); + for (int i=0; i<1000; ++i) + { + int& n = tss_value->value; + // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to + // be thread safe. Must evaluate further. + if (n != i) + { + boost::unique_lock<boost::mutex> lock(check_mutex); + BOOST_CHECK_EQUAL(n, i); + } + ++n; + } +} + + + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#if BOOST_PLAT_WINDOWS_RUNTIME + typedef std::shared_ptr<std::thread> native_thread_t; + + BOOST_AUTO_TEST_CASE(test_tss_thread_native) + { + test_tss_thread(); + } + + native_thread_t create_native_thread() + { + return std::make_shared<std::thread>(test_tss_thread_native); + } + + void join_native_thread(native_thread_t thread) + { + thread->join(); + } + +#else + typedef HANDLE native_thread_t; + + DWORD WINAPI test_tss_thread_native(LPVOID /*lpParameter*/) + { + test_tss_thread(); + return 0; + } + + native_thread_t create_native_thread(void) + { + native_thread_t const res=CreateThread( + 0, //security attributes (0 = not inheritable) + 0, //stack size (0 = default) + &test_tss_thread_native, //function to execute + 0, //parameter to pass to function + 0, //creation flags (0 = run immediately) + 0 //thread id (0 = thread id not returned) + ); + BOOST_CHECK(res!=0); + return res; + } + + void join_native_thread(native_thread_t thread) + { + DWORD res = WaitForSingleObject(thread, INFINITE); + BOOST_CHECK(res == WAIT_OBJECT_0); + + res = CloseHandle(thread); + BOOST_CHECK(SUCCEEDED(res)); + } +#endif +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) + typedef pthread_t native_thread_t; + +extern "C" +{ + void* test_tss_thread_native(void* ) + { + test_tss_thread(); + return 0; + } +} + + native_thread_t create_native_thread() + { + native_thread_t thread_handle; + + int const res = pthread_create(&thread_handle, 0, &test_tss_thread_native, 0); + BOOST_CHECK(!res); + return thread_handle; + } + + void join_native_thread(native_thread_t thread) + { + void* result=0; + int const res=pthread_join(thread,&result); + BOOST_CHECK(!res); + } +#endif + +void do_test_tss() +{ + tss_instances = 0; + tss_total = 0; + + const int NUMTHREADS=5; + boost::thread_group threads; + try + { + for (int i=0; i<NUMTHREADS; ++i) + threads.create_thread(&test_tss_thread); + threads.join_all(); + } + catch(...) + { + threads.interrupt_all(); + threads.join_all(); + throw; + } + + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + BOOST_CHECK_EQUAL(tss_instances, 0); + BOOST_CHECK_EQUAL(tss_total, 5); + + tss_instances = 0; + tss_total = 0; + + native_thread_t thread1 = create_native_thread(); + native_thread_t thread2 = create_native_thread(); + native_thread_t thread3 = create_native_thread(); + native_thread_t thread4 = create_native_thread(); + native_thread_t thread5 = create_native_thread(); + + join_native_thread(thread5); + join_native_thread(thread4); + join_native_thread(thread3); + join_native_thread(thread2); + join_native_thread(thread1); + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + // The following is not really an error. TSS cleanup support still is available for boost threads. + // Also this usually will be triggered only when bound to the static version of thread lib. + // 2006-10-02 Roland Schwarz + //BOOST_CHECK_EQUAL(tss_instances, 0); +#if !defined(__MINGW32__) + // This fails on MinGW, when using the static lib + BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available"); +#endif + BOOST_CHECK_EQUAL(tss_total, 5); +} + +BOOST_AUTO_TEST_CASE(test_tss) +{ + timed_test(&do_test_tss, 2); +} + + +bool tss_void_cleanup_called=false; + +void tss_void_custom_cleanup(void* d) +{ + std::cout << d << std::endl; + delete reinterpret_cast<tss_value_t*>(d); + tss_void_cleanup_called=true; +} + +boost::thread_specific_ptr<void> tss_void(tss_void_custom_cleanup); + +void test_tss_void_thread() +{ + tss_void.reset(new tss_value_t()); + for (int i=0; i<10; ++i) + { + int& n = static_cast<tss_value_t*>(tss_value.get())->value; + *tss_value; + // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to + // be thread safe. Must evaluate further. + if (n != i) + { + boost::unique_lock<boost::mutex> lock(check_mutex); + BOOST_CHECK_EQUAL(n, i); + } + ++n; + } +} +void do_test_tss_void() +{ + tss_instances = 0; + tss_total = 0; + + const int NUMTHREADS=5; + boost::thread_group threads; + try + { + for (int i=0; i<NUMTHREADS; ++i) + threads.create_thread(&test_tss_void_thread); + threads.join_all(); + } + catch(...) + { + threads.interrupt_all(); + threads.join_all(); + throw; + } + + + std::cout + << "tss_instances = " << tss_instances + << "; tss_total = " << tss_total + << "\n"; + std::cout.flush(); + + BOOST_CHECK_EQUAL(tss_instances, 0); + BOOST_CHECK_EQUAL(tss_total, 5); + +// tss_instances = 0; +// tss_total = 0; +// +// native_thread_t thread1 = create_native_thread(); +// native_thread_t thread2 = create_native_thread(); +// native_thread_t thread3 = create_native_thread(); +// native_thread_t thread4 = create_native_thread(); +// native_thread_t thread5 = create_native_thread(); +// +// join_native_thread(thread5); +// join_native_thread(thread4); +// join_native_thread(thread3); +// join_native_thread(thread2); +// join_native_thread(thread1); +// +// std::cout +// << "tss_instances = " << tss_instances +// << "; tss_total = " << tss_total +// << "\n"; +// std::cout.flush(); +// +// // The following is not really an error. TSS cleanup support still is available for boost threads. +// // Also this usually will be triggered only when bound to the static version of thread lib. +// // 2006-10-02 Roland Schwarz +// //BOOST_CHECK_EQUAL(tss_instances, 0); +// BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available"); +// BOOST_CHECK_EQUAL(tss_total, 5); +} + +//BOOST_AUTO_TEST_CASE(test_tss_void) +//{ +// timed_test(&do_test_tss_void, 2); +//} + + +boost::thread_specific_ptr<void> tss_void_with_cleanup(tss_void_custom_cleanup); + +void tss_void_thread_with_custom_cleanup() +{ + tss_void_with_cleanup.reset(new tss_value_t); +} + +void do_test_tss_void_with_custom_cleanup() +{ + boost::thread t(tss_void_thread_with_custom_cleanup); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(tss_void_cleanup_called); +} + + +BOOST_AUTO_TEST_CASE(test_tss_void_with_custom_cleanup) +{ + timed_test(&do_test_tss_void_with_custom_cleanup, 2); +} + + +bool tss_cleanup_called=false; + +struct Dummy +{}; + +void tss_custom_cleanup(Dummy* d) +{ + delete d; + tss_cleanup_called=true; +} + +boost::thread_specific_ptr<Dummy> tss_with_cleanup(tss_custom_cleanup); + +void tss_thread_with_custom_cleanup() +{ + tss_with_cleanup.reset(new Dummy); +} + +void do_test_tss_with_custom_cleanup() +{ + boost::thread t(tss_thread_with_custom_cleanup); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(tss_cleanup_called); +} + + +BOOST_AUTO_TEST_CASE(test_tss_with_custom_cleanup) +{ + timed_test(&do_test_tss_with_custom_cleanup, 2); +} + +Dummy* tss_object=new Dummy; + +void tss_thread_with_custom_cleanup_and_release() +{ + tss_with_cleanup.reset(tss_object); + tss_with_cleanup.release(); +} + +void do_test_tss_does_no_cleanup_after_release() +{ + tss_cleanup_called=false; + boost::thread t(tss_thread_with_custom_cleanup_and_release); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(!tss_cleanup_called); + if(!tss_cleanup_called) + { + delete tss_object; + } +} + +struct dummy_class_tracks_deletions +{ + static unsigned deletions; + + ~dummy_class_tracks_deletions() + { + ++deletions; + } + +}; + +unsigned dummy_class_tracks_deletions::deletions=0; + +boost::thread_specific_ptr<dummy_class_tracks_deletions> tss_with_null_cleanup(NULL); + +void tss_thread_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) +{ + tss_with_null_cleanup.reset(delete_tracker); +} + +void do_test_tss_does_no_cleanup_with_null_cleanup_function() +{ + dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions; + boost::thread t(tss_thread_with_null_cleanup,delete_tracker); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(!dummy_class_tracks_deletions::deletions); + if(!dummy_class_tracks_deletions::deletions) + { + delete delete_tracker; + } +} + +BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_after_release) +{ + timed_test(&do_test_tss_does_no_cleanup_after_release, 2); +} + +BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function) +{ + timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2); +} + +void thread_with_local_tss_ptr() +{ + { + boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); + + local_tss.reset(new Dummy); + } + BOOST_CHECK(tss_cleanup_called); + tss_cleanup_called=false; +} + + +BOOST_AUTO_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed) +{ + boost::thread t(thread_with_local_tss_ptr); + t.join(); + BOOST_CHECK(!tss_cleanup_called); +} + +BOOST_AUTO_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer) +{ + boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); + local_tss.reset(new Dummy); + tss_cleanup_called=false; + local_tss.reset(0); + BOOST_CHECK(tss_cleanup_called); + tss_cleanup_called=false; + local_tss.reset(new Dummy); + BOOST_CHECK(!tss_cleanup_called); +} + +//BOOST_AUTO_TEST_CASE(test_tss_at_the_same_adress) +//{ +// for(int i=0; i<2; i++) +// { +// boost::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup); +// local_tss.reset(new Dummy); +// tss_cleanup_called=false; +// BOOST_CHECK(tss_cleanup_called); +// tss_cleanup_called=false; +// BOOST_CHECK(!tss_cleanup_called); +// } +//} + diff --git a/src/boost/libs/thread/test/test_xtime.cpp b/src/boost/libs/thread/test/test_xtime.cpp new file mode 100644 index 000000000..4988d1f86 --- /dev/null +++ b/src/boost/libs/thread/test/test_xtime.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_THREAD_VERSION 2 +#define BOOST_TEST_MODULE Boost.Threads: xtime test suite + +#include <boost/thread/detail/config.hpp> + +#include <boost/thread/xtime.hpp> + +#include <boost/test/unit_test.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> + +BOOST_AUTO_TEST_CASE(test_xtime_cmp) +{ + boost::xtime xt1, xt2, cur; + BOOST_CHECK_EQUAL( + boost::xtime_get(&cur, boost::TIME_UTC_), + static_cast<int>(boost::TIME_UTC_)); + + xt1 = xt2 = cur; + xt1.nsec -= 1; + xt2.nsec += 1; + + BOOST_CHECK(boost::xtime_cmp(xt1, cur) < 0); + BOOST_CHECK(boost::xtime_cmp(xt2, cur) > 0); + BOOST_CHECK(boost::xtime_cmp(cur, cur) == 0); + + xt1 = xt2 = cur; + xt1.sec -= 1; + xt2.sec += 1; + + BOOST_CHECK(boost::xtime_cmp(xt1, cur) < 0); + BOOST_CHECK(boost::xtime_cmp(xt2, cur) > 0); + BOOST_CHECK(boost::xtime_cmp(cur, cur) == 0); +} + +BOOST_AUTO_TEST_CASE(test_xtime_get) +{ + boost::xtime orig, cur, old; + BOOST_CHECK_EQUAL( + boost::xtime_get(&orig, + boost::TIME_UTC_), static_cast<int>(boost::TIME_UTC_)); + old = orig; + + for (int x=0; x < 100; ++x) + { + BOOST_CHECK_EQUAL( + boost::xtime_get(&cur, boost::TIME_UTC_), + static_cast<int>(boost::TIME_UTC_)); + BOOST_CHECK(boost::xtime_cmp(cur, orig) >= 0); + BOOST_CHECK(boost::xtime_cmp(cur, old) >= 0); + old = cur; + } +} + +BOOST_AUTO_TEST_CASE(test_xtime_mutex_backwards_compatibility) +{ + boost::timed_mutex m; + BOOST_CHECK(m.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)))); + m.unlock(); + boost::timed_mutex::scoped_timed_lock lk(m,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + BOOST_CHECK(lk.owns_lock()); + if(lk.owns_lock()) + { + lk.unlock(); + } + BOOST_CHECK(lk.timed_lock(boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)))); + if(lk.owns_lock()) + { + lk.unlock(); + } +} + +bool predicate() +{ + return false; +} + + +BOOST_AUTO_TEST_CASE(test_xtime_condvar_backwards_compatibility) +{ + boost::condition_variable cond; + boost::condition_variable_any cond_any; + boost::mutex m; + + boost::unique_lock<boost::mutex> lk(m); + cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + cond.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate); + cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10))); + cond_any.timed_wait(lk,boost::get_xtime(boost::get_system_time()+boost::posix_time::milliseconds(10)),predicate); +} diff --git a/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp b/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp new file mode 100644 index 000000000..76047051f --- /dev/null +++ b/src/boost/libs/thread/test/threads/container/thread_ptr_list_pass.cpp @@ -0,0 +1,101 @@ +// Copyright (C) 2011 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_USES_MOVE + +#include <boost/config.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/csbl/list.hpp> +//#include <boost/interprocess/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + + +int count = 0; +boost::mutex mutex; + +namespace { + + +template <typename TC> +void join_all(TC & tc) +{ + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + (*it)->join(); + } +} + + +void increment_count() +{ + boost::unique_lock<boost::mutex> lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +template <class T> +struct default_delete +{ + typedef T* pointer; + + BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {} //= default; + template <class U> + default_delete(const default_delete<U>&) BOOST_NOEXCEPT + {} + void operator()(T* ptr) const + { + delete ptr; + } +}; + +} +int main() +{ + { + typedef boost::shared_ptr<boost::thread > thread_ptr; + //typedef boost::interprocess::shared_ptr<boost::thread, std::allocator<boost::thread>, default_delete<boost::thread> > thread_ptr; + typedef boost::csbl::list<thread_ptr > thread_ptr_list; + thread_ptr_list threads; + for (int i = 0; i < 10; ++i) + { + //threads.push_back(BOOST_THREAD_MAKE_RV_REF(thread_ptr(new boost::thread(&increment_count)))); + threads.push_back(thread_ptr(new boost::thread(&increment_count))); + } + BOOST_TEST(threads.size()==10); + //join_all(threads); + for (thread_ptr_list::iterator it = threads.begin(); it != threads.end(); ++it) + { + (*it)->join(); + } + } + count = 0; + { + typedef boost::shared_ptr<boost::thread > thread_ptr; + //typedef boost::interprocess::shared_ptr<boost::thread, std::allocator<boost::thread>, default_delete<boost::thread> > thread_ptr; + typedef boost::csbl::list<thread_ptr > thread_ptr_list; + thread_ptr_list threads; + for (int i = 0; i < 10; ++i) + { + //threads.push_back(BOOST_THREAD_MAKE_RV_REF(thread_ptr(new boost::thread(&increment_count)))); + threads.push_back(thread_ptr(new boost::thread(&increment_count))); + } + BOOST_TEST(threads.size()==10); + thread_ptr sth(new boost::thread(&increment_count)); + threads.push_back(sth); + BOOST_TEST(threads.size()==11); + threads.remove(sth); + BOOST_TEST(threads.size()==10); + sth->join(); + //join_all(threads); + for (thread_ptr_list::iterator it = threads.begin(); it != threads.end(); ++it) + { + (*it)->join(); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp b/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp new file mode 100644 index 000000000..059a77e36 --- /dev/null +++ b/src/boost/libs/thread/test/threads/container/thread_vector_pass.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2011 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_USES_MOVE + +#include <boost/thread/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/csbl/vector.hpp> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +int count = 0; +boost::mutex mutex; + +namespace +{ +template <typename TC> +void join_all(TC & tc) +{ + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + it->join(); + } +} + +template <typename TC> +void interrupt_all(TC & tc) +{ +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + for (typename TC::iterator it = tc.begin(); it != tc.end(); ++it) + { + it->interrupt(); + } +#endif +} +} + +void increment_count() +{ + boost::unique_lock<boost::mutex> lock(mutex); + std::cout << "count = " << ++count << std::endl; +} + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_THREAD_USES_MOVE +BOOST_STATIC_ASSERT(::boost::is_function<boost::rv<boost::rv<boost::thread> >&>::value==false); +#endif + +int main() +{ + typedef boost::csbl::vector<boost::thread> thread_vector; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + boost::thread th(&increment_count); + threads.push_back(boost::move(th)); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.push_back(BOOST_THREAD_MAKE_RV_REF(boost::thread(&increment_count))); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.emplace_back(&increment_count); + } + join_all(threads); + } + count = 0; + { + thread_vector threads; + threads.reserve(10); + for (int i = 0; i < 10; ++i) + { + threads.emplace_back(&increment_count); + } + interrupt_all(threads); + join_all(threads); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp new file mode 100644 index 000000000..f0287cb6a --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/get_id/get_id_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::thread::id id = boost::this_thread::get_id(); + BOOST_TEST(id != boost::thread::id()); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp new file mode 100644 index 000000000..05c5a790d --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/sleep_for/sleep_for_pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <algorithm> + +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +int main() +{ + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_for(ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_for(ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + return boost::report_errors(); + +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp b/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp new file mode 100644 index 000000000..232712eed --- /dev/null +++ b/src/boost/libs/thread/test/threads/this_thread/sleep_until/sleep_until_pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// thread::id this_thread::get_id(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <algorithm> + +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +int main() +{ + { + typedef boost::chrono::steady_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::steady_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + { + typedef boost::chrono::system_clock Clock; + typedef Clock::time_point time_point; + //typedef Clock::duration duration; + boost::chrono::milliseconds ms(500); + time_point t0 = Clock::now(); + boost::this_thread::no_interruption_point::sleep_until(t0 + ms); + time_point t1 = Clock::now(); + boost::chrono::nanoseconds ns = (t1 - t0) - ms; + boost::chrono::nanoseconds err = ms / 100; + // The time slept is within 1% of 500ms + // This test is spurious as it depends on the time the thread system switches the threads + BOOST_TEST((std::max)(ns.count(), -ns.count()) < (err+boost::chrono::milliseconds(1000)).count()); + //BOOST_TEST(std::abs(static_cast<long>(ns.count())) < (err+boost::chrono::milliseconds(1000)).count()); + } + return boost::report_errors(); + +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif + diff --git a/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp b/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp new file mode 100644 index 000000000..5ccac5b31 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/assign/copy_fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// thread& operator=(thread&& t); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread t1; + t1 = t0; + } +} + +#include "../../../remove_error_code_unused_warning.hpp" diff --git a/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp b/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp new file mode 100644 index 000000000..293c5d838 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/assign/move_pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// thread& operator=(thread&& t); + +#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +void f1() +{ + std::exit(boost::report_errors()); +} + +int main() +{ + std::set_terminate(f1); + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0(G(), 5, 5.5); + boost::thread::id id = t0.get_id(); + boost::thread t1; + t1 = boost::move(t0); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::op_run); + } + BOOST_TEST(G::n_alive == 0); + { + boost::thread t0(G(), 5, 5.5); + boost::thread t1; + t0 = boost::move(t1); + BOOST_TEST(false); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp new file mode 100644 index 000000000..afdc7018f --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/FArgs_pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F f, Args... args); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + std::free(p); +} + +bool f_run = false; + +void f(int i, double j) +{ + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + f_run = true; +} + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive >= 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + + +int main() +{ + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + boost::thread t(f, 5, 5.5); + t.join(); + BOOST_TEST(f_run == true); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + f_run = false; + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + try + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + throw_one = 0; + boost::thread t(f, 5, 5.5); + BOOST_TEST(false); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + catch (...) + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } +#endif + { + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(G::n_alive == 0); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(!G::op_run); + boost::thread t(G(), 5, 5.5); + t.join(); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp new file mode 100644 index 000000000..7fd2bbc24 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/F_pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F f, Args... args); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + //std::cout << __FILE__ << ":" << __LINE__ << std::endl; + std::free(p); +} + +bool f_run = false; + +void f() +{ + f_run = true; +} + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive >= 1); + op_run = true; + } + +}; + +int G::n_alive = 0; +bool G::op_run = false; + + +int main() +{ + { + boost::thread t(f); + t.join(); + BOOST_TEST(f_run == true); + } + f_run = false; +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + { + try + { + throw_one = 0; + boost::thread t(f); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + } + } +#endif + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); + t.join(); + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + G::op_run = false; + { + try + { + throw_one = 0; + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(G::n_alive == 0); + std::cout << __FILE__ << ":" << __LINE__ <<" " << G::n_alive << std::endl; + BOOST_TEST(!G::op_run); + } + } +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp new file mode 100644 index 000000000..e76db7022 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F&& f, Args&&... args); + +#define BOOST_THREAD_VERSION 4 + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class MoveOnly +{ +public: + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()(BOOST_THREAD_RV_REF(MoveOnly)) + { + } +}; + +class M +{ + +public: + long data_; + static int n_moves; + + BOOST_THREAD_MOVABLE_ONLY(M) + static void reset() { + n_moves=0; + } + explicit M(long i) : data_(i) + { + } + M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_) + { + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + } + M& operator=(BOOST_THREAD_RV_REF(M) a) + { + data_ = BOOST_THREAD_RV(a).data_; + BOOST_THREAD_RV(a).data_ = -1; + ++n_moves; + return *this; + } + ~M() + { + } + + void operator()(int) const + { } + long operator()() const + { return data_;} + long operator()(long i, long j) const + { return data_ + i + j;} +}; + +int M::n_moves = 0; + +void fct(BOOST_THREAD_RV_REF(M) v) +{ + BOOST_TEST_EQ(v.data_, 1); +} + +int main() +{ +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + { + boost::thread t = boost::thread( MoveOnly(), MoveOnly() ); + t.join(); + } + { + M::reset(); + boost::thread t = boost::thread( fct, M(1) ); + t.join(); + BOOST_TEST_EQ(M::n_moves, 2); + } +#endif + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp new file mode 100644 index 000000000..38061e0a7 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/Frvalue_pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class F, class ...Args> thread(F&& f, Args&&... args); + +#define BOOST_THREAD_USES_MOVE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +class MoveOnly +{ +public: + BOOST_THREAD_MOVABLE_ONLY(MoveOnly) + MoveOnly() + { + } + MoveOnly(BOOST_THREAD_RV_REF(MoveOnly)) + {} + + void operator()() + { + } +}; + +MoveOnly MakeMoveOnly() { + return BOOST_THREAD_MAKE_RV_REF(MoveOnly()); +} + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_THREAD_USES_MOVE +BOOST_STATIC_ASSERT(::boost::is_function<boost::rv<boost::rv<MoveOnly> >&>::value==false); +#endif + +int main() +{ + { + boost::thread t(( BOOST_THREAD_MAKE_RV_REF(MakeMoveOnly()) )); + t.join(); + } + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp b/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp new file mode 100644 index 000000000..caa72c2d8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/copy_fail.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(const thread&) = delete; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0(G(), 5, 5.5); + boost::thread::id id = t0.get_id(); + boost::thread t1( (t0)); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(G::op_run); + } +} + +#include "../../../remove_error_code_unused_warning.hpp" + diff --git a/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp new file mode 100644 index 000000000..cea602d15 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/default_pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(); + +#include <boost/thread/thread_only.hpp> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + boost::thread t; + BOOST_TEST(t.get_id() == boost::thread::id()); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp new file mode 100644 index 000000000..84615bf88 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/lambda_pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Clousure> thread(Clousure f); + +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_NO_CXX11_LAMBDAS + +unsigned throw_one = 0xFFFF; + +#if defined _GLIBCXX_THROW +void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc) +#elif defined BOOST_MSVC +void* operator new(std::size_t s) +#elif __cplusplus > 201402L +void* operator new(std::size_t s) +#else +void* operator new(std::size_t s) throw (std::bad_alloc) +#endif +{ + if (throw_one == 0) throw std::bad_alloc(); + --throw_one; + return std::malloc(s); +} + +#if defined BOOST_MSVC +void operator delete(void* p) +#else +void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW +#endif +{ + std::free(p); +} + +bool f_run = false; + +int main() +{ + { + f_run = false; + boost::thread t( []() { f_run = true; } ); + t.join(); + BOOST_TEST(f_run == true); + } +#if !defined(BOOST_MSVC) && !defined(__MINGW32__) + { + f_run = false; + try + { + throw_one = 0; + boost::thread t( []() { f_run = true; } ); + BOOST_TEST(false); + } + catch (...) + { + throw_one = 0xFFFF; + BOOST_TEST(!f_run); + } + } +#endif + + return boost::report_errors(); +} + +#else +int main() +{ + return 0; +} +#endif diff --git a/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp b/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp new file mode 100644 index 000000000..66f9d7546 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/constr/move_pass.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// thread(thread&& t); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } + + void operator()(int i, double j) + { + BOOST_TEST(alive_ == 1); + std::cout << __FILE__ << ":" << __LINE__ <<" " << n_alive << std::endl; + //BOOST_TEST(n_alive == 1); + BOOST_TEST(i == 5); + BOOST_TEST(j == 5.5); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +boost::thread make_thread() { + return boost::thread(G(), 5, 5.5); +} + +int main() +{ + { + //BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t0((G())); + boost::thread::id id = t0.get_id(); + boost::thread t1((boost::move(t0))); + BOOST_TEST(t1.get_id() == id); + BOOST_TEST(t0.get_id() == boost::thread::id()); + t1.join(); + BOOST_TEST(G::op_run); + } + //BOOST_TEST(G::n_alive == 0); + { + boost::thread t1((BOOST_THREAD_MAKE_RV_REF(make_thread()))); + t1.join(); + BOOST_TEST(G::op_run); + } + //BOOST_TEST(G::n_alive == 0); + return boost::report_errors(); +} diff --git a/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp b/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp new file mode 100644 index 000000000..ea0e6bac4 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/destr/dtor_pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// ~thread(); + +#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +void f1() +{ + std::exit(boost::report_errors()); +} + +int main() +{ + std::set_terminate(f1); + { + BOOST_TEST(G::n_alive == 0); + BOOST_TEST(!G::op_run); + boost::thread t( (G())); +#if defined BOOST_THREAD_USES_CHRONO + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +#endif + BOOST_TEST(t.joinable()); + } + BOOST_TEST(false); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp b/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp new file mode 100644 index 000000000..6ce52c97a --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/id/hash_pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// <functional> + +// template <class T> +// struct hash +// : public unary_function<T, size_t> +// { +// size_t operator()(T val) const; +// }; + + +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + { + boost::thread::id id1; + boost::thread::id id2 = boost::this_thread::get_id(); + typedef boost::hash<boost::thread::id> H; + H h; + BOOST_TEST(h(id1) != h(id2)); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp new file mode 100644 index 000000000..927175338 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/detach_pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// void detach(); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.detach(); + BOOST_TEST(!t0.joinable()); +#if defined BOOST_THREAD_USES_CHRONO + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + BOOST_TEST(G::op_run); + BOOST_TEST(G::n_alive == 0); +#endif + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp new file mode 100644 index 000000000..dcaa7090b --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/get_id_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// id get_id() const; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + //boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + BOOST_TEST(t0.get_id() != id1); + BOOST_TEST(t1.get_id() == boost::thread::id()); + t0.join(); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp new file mode 100644 index 000000000..f2d42b72b --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/join_pass.cpp @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// void join(); +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp new file mode 100644 index 000000000..dcf09d1f8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/joinable_pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// bool joinable() const; + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp new file mode 100644 index 000000000..01115da05 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/native_handle_pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// native_handle_type native_handle(); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + // boost::thread::native_handle_type hdl = + (void)t0.native_handle(); + t0.join(); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp new file mode 100644 index 000000000..16af2d1b8 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/swap_pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// native_handle_type native_handle(); + +#include <boost/thread/thread_only.hpp> +#include <cstdlib> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + std::cout << n_alive << std::endl; + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + t0.swap(t1); + BOOST_TEST(t0.get_id() == id1); + BOOST_TEST(t1.get_id() == id0); + t1.join(); + return boost::report_errors(); + } +} + diff --git a/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp new file mode 100644 index 000000000..5215d18d6 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/try_join_for_pass.cpp @@ -0,0 +1,161 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Rep, class Period> +// bool try_join_for(const chrono::duration<Rep, Period>& rel_time); + +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +class G +{ + int alive_; +public: + static bool op_run; + + G() : + alive_(1) + { + } + G(const G& g) : + alive_(g.alive_) + { + } + ~G() + { + alive_ = 0; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + op_run = true; + } +}; + +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +void th_250_ms() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +} + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + BOOST_TEST(t0.try_join_for(boost::chrono::milliseconds(250))); + BOOST_TEST(!t0.joinable()); + } + { + boost::thread t0( (th_250_ms)); + BOOST_TEST(!t0.try_join_for(boost::chrono::milliseconds(50))); + t0.join(); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.try_join_for(boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_for(boost::chrono::milliseconds(250)); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp b/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp new file mode 100644 index 000000000..749ff5b06 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/members/try_join_until_pass.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// template <class Clock, class Duration> +// bool try_join_until(const chrono::time_point<Clock, Duration>& t); + +#define BOOST_THREAD_VESRION 3 +#include <boost/thread/thread_only.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/locks.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <boost/detail/lightweight_test.hpp> + +#if defined BOOST_THREAD_USES_CHRONO + +class G +{ + int alive_; +public: + static bool op_run; + + G() : + alive_(1) + { + } + G(const G& g) : + alive_(g.alive_) + { + } + ~G() + { + alive_ = 0; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + op_run = true; + } +}; + +bool G::op_run = false; + +boost::thread* resource_deadlock_would_occur_th=0; +boost::mutex resource_deadlock_would_occur_mtx; +void resource_deadlock_would_occur_tester() +{ + try + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + resource_deadlock_would_occur_th->try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::resource_deadlock_would_occur); + } + catch (...) + { + BOOST_TEST(false&&"exception thrown"); + } +} + +void th_250_ms() +{ + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); +} + + +int main() +{ + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(250)); + BOOST_TEST(!t0.joinable()); + } + { + boost::thread t0( (th_250_ms)); + BOOST_TEST(!t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50))); + t0.join(); + } + + { + boost::unique_lock<boost::mutex> lk(resource_deadlock_would_occur_mtx); + boost::thread t0( resource_deadlock_would_occur_tester ); + resource_deadlock_would_occur_th = &t0; + BOOST_TEST(t0.joinable()); + lk.unlock(); + boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); + boost::unique_lock<boost::mutex> lk2(resource_deadlock_would_occur_mtx); + t0.join(); + BOOST_TEST(!t0.joinable()); + } + + { + boost::thread t0( (G())); + t0.detach(); + try + { + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.join(); + try + { + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(50)); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + { + boost::thread t0( (G())); + BOOST_TEST(t0.joinable()); + t0.try_join_until(boost::chrono::steady_clock::now()+boost::chrono::milliseconds(250)); + try + { + t0.join(); + BOOST_TEST(false); + } + catch (boost::system::system_error& e) + { + BOOST_TEST(e.code().value() == boost::system::errc::invalid_argument); + } + + } + + return boost::report_errors(); +} + +#else +#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported" +#endif diff --git a/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp b/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp new file mode 100644 index 000000000..eb6faf157 --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/non_members/swap_pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// void swap(thread& x, thread& y); + +#include <boost/thread/thread_only.hpp> +#include <new> +#include <cstdlib> +#include <cassert> +#include <boost/detail/lightweight_test.hpp> + +class G +{ + int alive_; +public: + static int n_alive; + static bool op_run; + + G() : + alive_(1) + { + ++n_alive; + } + G(const G& g) : + alive_(g.alive_) + { + ++n_alive; + } + ~G() + { + alive_ = 0; + --n_alive; + } + + void operator()() + { + BOOST_TEST(alive_ == 1); + //BOOST_TEST(n_alive == 1); + op_run = true; + } +}; + +int G::n_alive = 0; +bool G::op_run = false; + +int main() +{ + { + boost::thread t0( (G())); + boost::thread::id id0 = t0.get_id(); + boost::thread t1; + boost::thread::id id1 = t1.get_id(); + swap(t0, t1); + BOOST_TEST(t0.get_id() == id1); + BOOST_TEST(t1.get_id() == id0); + t1.join(); + } + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp b/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp new file mode 100644 index 000000000..2a2a227ed --- /dev/null +++ b/src/boost/libs/thread/test/threads/thread/static/hardware_concurrency_pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Copyright (C) 2011 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) + +// <boost/thread/thread.hpp> + +// class thread + +// static unsigned hardware_concurrency(); + +#include <boost/thread/thread_only.hpp> +#include <boost/detail/lightweight_test.hpp> + +int main() +{ + BOOST_TEST(boost::thread::hardware_concurrency() > 0); + return boost::report_errors(); +} + diff --git a/src/boost/libs/thread/test/timming.hpp b/src/boost/libs/thread/test/timming.hpp new file mode 100644 index 000000000..6ae320e8d --- /dev/null +++ b/src/boost/libs/thread/test/timming.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018 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) + +#ifndef BOOST_THREAD_TEST_TIMMING_HPP +#define BOOST_THREAD_TEST_TIMMING_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/detail/lightweight_test.hpp> + +#if ! defined BOOST_THREAD_TEST_TIME_MS +#ifdef __linux__ +#define BOOST_THREAD_TEST_TIME_MS 75 +#else +// Windows, Cygwin, macOS all need this +#define BOOST_THREAD_TEST_TIME_MS 250 +#endif +#endif + +#if ! defined BOOST_THREAD_TEST_TIME_WARNING +#define BOOST_THREAD_TEST_IT(A, B) BOOST_TEST_LT((A).count(), (B).count()) +#else +#define BOOST_THREAD_TEST_IT(A, B) BOOST_TEST_LT((A).count(), (B).count()) +#endif + +#endif diff --git a/src/boost/libs/thread/test/util.inl b/src/boost/libs/thread/test/util.inl new file mode 100644 index 000000000..e4709bc3e --- /dev/null +++ b/src/boost/libs/thread/test/util.inl @@ -0,0 +1,243 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(UTIL_INL_WEK01242003) +#define UTIL_INL_WEK01242003 + +#include <boost/thread/xtime.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/thread.hpp> +#include <boost/config.hpp> + +#ifndef DEFAULT_EXECUTION_MONITOR_TYPE +# define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_condition +#endif + +// boostinspect:nounnamed + + + +namespace +{ +inline boost::xtime delay(int secs, int msecs=0, int nsecs=0) +{ + const int MILLISECONDS_PER_SECOND = 1000; + const int NANOSECONDS_PER_SECOND = 1000000000; + const int NANOSECONDS_PER_MILLISECOND = 1000000; + + boost::xtime xt; + if (boost::TIME_UTC_ != boost::xtime_get (&xt, boost::TIME_UTC_)) + BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC_"); + + nsecs += xt.nsec; + msecs += nsecs / NANOSECONDS_PER_MILLISECOND; + secs += msecs / MILLISECONDS_PER_SECOND; + nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; + xt.nsec = nsecs % NANOSECONDS_PER_SECOND; + xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND); + + return xt; +} + +} +namespace boost +{ +namespace threads +{ +namespace test +{ +inline bool in_range(const boost::xtime& xt, int secs=1) +{ + boost::xtime min = delay(-secs); + boost::xtime max = delay(0); + return (boost::xtime_cmp(xt, min) >= 0) && + (boost::xtime_cmp(xt, max) <= 0); +} +} +} +} + + +namespace +{ +class execution_monitor +{ +public: + enum wait_type { use_sleep_only, use_mutex, use_condition }; + + execution_monitor(wait_type type, int secs) + : done(false), type(type), secs(secs) { } + void start() + { + if (type != use_sleep_only) { + boost::unique_lock<boost::mutex> lock(mutex); done = false; + } else { + done = false; + } + } + void finish() + { + if (type != use_sleep_only) { + boost::unique_lock<boost::mutex> lock(mutex); + done = true; + if (type == use_condition) + cond.notify_one(); + } else { + done = true; + } + } + bool wait() + { + boost::xtime xt = delay(secs); + if (type == use_sleep_only) { + boost::thread::sleep(xt); + return done; + } + if (type == use_condition) { + boost::unique_lock<boost::mutex> lock(mutex); + while (!done) { + if (!cond.timed_wait(lock, xt)) + break; + } + return done; + } + for (int i = 0; ; ++i) { + { + boost::unique_lock<boost::mutex> lock(mutex); + if (done) + return true; + else if (i > secs * 2) + return done; + } + boost::thread::sleep(delay(0, 500)); + } + } + +private: + boost::mutex mutex; + boost::condition cond; + bool done; + wait_type type; + int secs; +}; +} +namespace thread_detail_anon +{ +template <typename F> +class indirect_adapter +{ +public: + indirect_adapter(F func, execution_monitor& monitor) + : func(func), monitor(monitor) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + indirect_adapter(indirect_adapter const&) = default; +#endif + + void operator()() const + { + try + { + boost::thread thrd(func); + thrd.join(); + } + catch (...) + { + monitor.finish(); + throw; + } + monitor.finish(); + } + +private: + F func; + execution_monitor& monitor; + void operator=(indirect_adapter&); +}; + +} +// boostinspect:nounnamed +namespace +{ + +template <typename F> +void timed_test(F func, int secs, + execution_monitor::wait_type type=DEFAULT_EXECUTION_MONITOR_TYPE) +{ + execution_monitor monitor(type, secs); + thread_detail_anon::indirect_adapter<F> ifunc(func, monitor); + monitor.start(); + boost::thread thrd(ifunc); + BOOST_REQUIRE_MESSAGE(monitor.wait(), + "Timed test didn't complete in time, possible deadlock."); +} + +} + +namespace thread_detail_anon +{ + +template <typename F, typename T> +class thread_binder +{ +public: + thread_binder(const F& func, const T& param) + : func(func), param(param) { } + void operator()() const { func(param); } + +private: + F func; + T param; +}; + +} + +// boostinspect:nounnamed +namespace +{ +template <typename F, typename T> +thread_detail_anon::thread_binder<F, T> bind(const F& func, const T& param) +{ + return thread_detail_anon::thread_binder<F, T>(func, param); +} +} + +namespace thread_detail_anon +{ + +template <typename R, typename T> +class thread_member_binder +{ +public: + thread_member_binder(R (T::*func)(), T& param) + : func(func), param(param) { } +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + thread_member_binder(thread_member_binder const&) = default; +#endif + + void operator()() const { (param.*func)(); } + +private: + void operator=(thread_member_binder&); + + R (T::*func)(); + T& param; +}; + +} + +// boostinspect:nounnamed +namespace +{ +template <typename R, typename T> +thread_detail_anon::thread_member_binder<R, T> bind(R (T::*func)(), T& param) +{ + return thread_detail_anon::thread_member_binder<R, T>(func, param); +} +} // namespace + +#endif diff --git a/src/boost/libs/thread/test/winrt_init.cpp b/src/boost/libs/thread/test/winrt_init.cpp new file mode 100644 index 000000000..b6d0864ba --- /dev/null +++ b/src/boost/libs/thread/test/winrt_init.cpp @@ -0,0 +1,19 @@ +// 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 <boost/predef/platform.h> + +#if BOOST_PLAT_WINDOWS_RUNTIME + +#include <wrl\wrappers\corewrappers.h> +#pragma comment(lib, "runtimeobject.lib") + +// Necessary for the tests which to keep the Windows Runtime active, +// when running in an actual Windows store/phone application initialization +// is handled automatically by the CRT. +// This is easier than calling in the main function for each test case. +Microsoft::WRL::Wrappers::RoInitializeWrapper runtime(RO_INIT_MULTITHREADED); + +#endif diff --git a/src/boost/libs/thread/tutorial/bounded_buffer.cpp b/src/boost/libs/thread/tutorial/bounded_buffer.cpp new file mode 100644 index 000000000..276aaebf1 --- /dev/null +++ b/src/boost/libs/thread/tutorial/bounded_buffer.cpp @@ -0,0 +1,69 @@ +// 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 <boost/thread/condition.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <iostream> +#include <vector> + +class bounded_buffer : private boost::noncopyable +{ +public: + typedef boost::mutex::scoped_lock lock; + bounded_buffer(int n) : 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, buffered; + std::vector<int> circular_buf; + boost::condition buffer_not_full, buffer_not_empty; + boost::mutex monitor; +}; +bounded_buffer buf(2); + +void sender() { + int n = 0; + while (n < 100) { + buf.send(n); + std::cout << "sent: " << n << std::endl; + ++n; + } + buf.send(-1); +} + +void receiver() { + int n; + do { + n = buf.receive(); + std::cout << "received: " << n << std::endl; + } while (n != -1); // -1 indicates end of buffer +} + +int main() +{ + boost::thread thrd1(&sender); + boost::thread thrd2(&receiver); + thrd1.join(); + thrd2.join(); +} diff --git a/src/boost/libs/thread/tutorial/counter.cpp b/src/boost/libs/thread/tutorial/counter.cpp new file mode 100644 index 000000000..a5ca0b4d6 --- /dev/null +++ b/src/boost/libs/thread/tutorial/counter.cpp @@ -0,0 +1,28 @@ +// 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 <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <iostream> + +boost::mutex mutex; +int counter=0; + +void change_count() +{ + boost::mutex::scoped_lock lock(mutex); + int i = ++counter; + std::cout << "count == " << i << std::endl; +} + +int main() +{ + 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(); +} diff --git a/src/boost/libs/thread/tutorial/factorial.cpp b/src/boost/libs/thread/tutorial/factorial.cpp new file mode 100644 index 000000000..9dd1001d9 --- /dev/null +++ b/src/boost/libs/thread/tutorial/factorial.cpp @@ -0,0 +1,32 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +class factorial +{ +public: + factorial(int x, int& res) : x(x), res(res) { } + void operator()() { res = calculate(x); } + int result() const { return res; } + +private: + int calculate(int x) { return x <= 1 ? 1 : x * calculate(x-1); } + +private: + int x; + int& res; +}; + +int main() +{ + int result; + factorial f(10, result); + boost::thread thrd(f); + thrd.join(); + std::cout << "10! = " << result << std::endl; +} diff --git a/src/boost/libs/thread/tutorial/factorial2.cpp b/src/boost/libs/thread/tutorial/factorial2.cpp new file mode 100644 index 000000000..c30421bc5 --- /dev/null +++ b/src/boost/libs/thread/tutorial/factorial2.cpp @@ -0,0 +1,32 @@ +// 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 <boost/thread/thread.hpp> +#include <boost/ref.hpp> +#include <iostream> + +class factorial +{ +public: + factorial(int x) : x(x), res(0) { } + void operator()() { res = calculate(x); } + int result() const { return res; } + +private: + int calculate(int x) { return x <= 1 ? 1 : x * calculate(x-1); } + +private: + int x; + int res; +}; + +int main() +{ + factorial f(10); + boost::thread thrd(boost::ref(f)); + thrd.join(); + std::cout << "10! = " << f.result() << std::endl; +} diff --git a/src/boost/libs/thread/tutorial/factorial3.cpp b/src/boost/libs/thread/tutorial/factorial3.cpp new file mode 100644 index 000000000..2515bfeab --- /dev/null +++ b/src/boost/libs/thread/tutorial/factorial3.cpp @@ -0,0 +1,36 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +const int NUM_CALCS=5; + +class factorial +{ +public: + factorial(int x, int& res) : x(x), res(res) { } + void operator()() { res = calculate(x); } + int result() const { return res; } + +private: + int calculate(int x) { return x <= 1 ? 1 : x * calculate(x-1); } + +private: + int x; + int& res; +}; + +int main() +{ + int results[NUM_CALCS]; + boost::thread_group thrds; + for (int i=0; i < NUM_CALCS; ++i) + thrds.create_thread(factorial(i*10, results[i])); + thrds.join_all(); + for (int j=0; j < NUM_CALCS; ++j) + std::cout << j*10 << "! = " << results[j] << std::endl; +} diff --git a/src/boost/libs/thread/tutorial/helloworld.cpp b/src/boost/libs/thread/tutorial/helloworld.cpp new file mode 100644 index 000000000..5003108f4 --- /dev/null +++ b/src/boost/libs/thread/tutorial/helloworld.cpp @@ -0,0 +1,19 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +void helloworld() +{ + std::cout << "Hello World!" << std::endl; +} + +int main() +{ + boost::thread thrd(&helloworld); + thrd.join(); +} diff --git a/src/boost/libs/thread/tutorial/helloworld2.cpp b/src/boost/libs/thread/tutorial/helloworld2.cpp new file mode 100644 index 000000000..dc7a698a8 --- /dev/null +++ b/src/boost/libs/thread/tutorial/helloworld2.cpp @@ -0,0 +1,24 @@ +// 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 <boost/thread/thread.hpp> +#include <iostream> + +struct helloworld +{ + helloworld(const char* who) : m_who(who) { } + void operator()() + { + std::cout << m_who << "says, \"Hello World.\"" << std::endl; + } + const char* m_who; +}; + +int main() +{ + boost::thread thrd(helloworld("Bob")); + thrd.join(); +} diff --git a/src/boost/libs/thread/tutorial/helloworld3.cpp b/src/boost/libs/thread/tutorial/helloworld3.cpp new file mode 100644 index 000000000..239ed8fe2 --- /dev/null +++ b/src/boost/libs/thread/tutorial/helloworld3.cpp @@ -0,0 +1,20 @@ +// 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 <boost/thread/thread.hpp> +#include <boost/bind/bind.hpp> +#include <iostream> + +void helloworld(const char* who) +{ + std::cout << who << "says, \"Hello World.\"" << std::endl; +} + +int main() +{ + boost::thread thrd(boost::bind(&helloworld, "Bob")); + thrd.join(); +} diff --git a/src/boost/libs/thread/tutorial/once.cpp b/src/boost/libs/thread/tutorial/once.cpp new file mode 100644 index 000000000..5a5b6f558 --- /dev/null +++ b/src/boost/libs/thread/tutorial/once.cpp @@ -0,0 +1,31 @@ +// 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 <boost/thread/thread.hpp> +#include <boost/thread/once.hpp> +#include <cassert> + +int value=0; +boost::once_flag once = BOOST_ONCE_INIT; + +void init() +{ + ++value; +} + +void thread_proc() +{ + boost::call_once(&init, once); +} + +int main(int argc, char* argv[]) +{ + 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/tutorial/tss.cpp b/src/boost/libs/thread/tutorial/tss.cpp new file mode 100644 index 000000000..f867a9180 --- /dev/null +++ b/src/boost/libs/thread/tutorial/tss.cpp @@ -0,0 +1,36 @@ +// 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 <boost/thread/thread.hpp> +#include <boost/thread/tss.hpp> +#include <cassert> + +boost::thread_specific_ptr<int> 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); + } +} + +int main(int argc, char* argv[]) +{ + boost::thread_group threads; + for (int i=0; i<5; ++i) + threads.create_thread(&thread_proc); + threads.join_all(); +} |