summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/fiber/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/fiber/test
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/fiber/test')
-rw-r--r--src/boost/libs/fiber/test/Jamfile.v21294
-rw-r--r--src/boost/libs/fiber/test/test_async_dispatch.cpp157
-rw-r--r--src/boost/libs/fiber/test/test_async_post.cpp131
-rw-r--r--src/boost/libs/fiber/test/test_barrier_dispatch.cpp71
-rw-r--r--src/boost/libs/fiber/test/test_barrier_post.cpp71
-rw-r--r--src/boost/libs/fiber/test/test_buffered_channel_dispatch.cpp531
-rw-r--r--src/boost/libs/fiber/test/test_buffered_channel_post.cpp529
-rw-r--r--src/boost/libs/fiber/test/test_condition_mt_dispatch.cpp164
-rw-r--r--src/boost/libs/fiber/test/test_condition_mt_post.cpp164
-rw-r--r--src/boost/libs/fiber/test/test_condition_variable_any_dispatch.cpp501
-rw-r--r--src/boost/libs/fiber/test/test_condition_variable_any_post.cpp501
-rw-r--r--src/boost/libs/fiber/test/test_condition_variable_dispatch.cpp495
-rw-r--r--src/boost/libs/fiber/test/test_condition_variable_post.cpp495
-rw-r--r--src/boost/libs/fiber/test/test_fiber_dispatch.cpp440
-rw-r--r--src/boost/libs/fiber/test/test_fiber_post.cpp440
-rw-r--r--src/boost/libs/fiber/test/test_fss_dispatch.cpp237
-rw-r--r--src/boost/libs/fiber/test/test_fss_post.cpp237
-rw-r--r--src/boost/libs/fiber/test/test_future_dispatch.cpp569
-rw-r--r--src/boost/libs/fiber/test/test_future_mt_dispatch.cpp50
-rw-r--r--src/boost/libs/fiber/test/test_future_mt_post.cpp50
-rw-r--r--src/boost/libs/fiber/test/test_future_post.cpp569
-rw-r--r--src/boost/libs/fiber/test/test_mutex_dispatch.cpp447
-rw-r--r--src/boost/libs/fiber/test/test_mutex_mt_dispatch.cpp139
-rw-r--r--src/boost/libs/fiber/test/test_mutex_mt_post.cpp139
-rw-r--r--src/boost/libs/fiber/test/test_mutex_post.cpp447
-rw-r--r--src/boost/libs/fiber/test/test_packaged_task_dispatch.cpp679
-rw-r--r--src/boost/libs/fiber/test/test_packaged_task_post.cpp679
-rw-r--r--src/boost/libs/fiber/test/test_promise_dispatch.cpp445
-rw-r--r--src/boost/libs/fiber/test/test_promise_post.cpp445
-rw-r--r--src/boost/libs/fiber/test/test_shared_future_dispatch.cpp608
-rw-r--r--src/boost/libs/fiber/test/test_shared_future_post.cpp608
-rw-r--r--src/boost/libs/fiber/test/test_unbuffered_channel_dispatch.cpp451
-rw-r--r--src/boost/libs/fiber/test/test_unbuffered_channel_post.cpp451
33 files changed, 13234 insertions, 0 deletions
diff --git a/src/boost/libs/fiber/test/Jamfile.v2 b/src/boost/libs/fiber/test/Jamfile.v2
new file mode 100644
index 00000000..fac5c9e2
--- /dev/null
+++ b/src/boost/libs/fiber/test/Jamfile.v2
@@ -0,0 +1,1294 @@
+# Boost.Fiber Library Tests Jamfile
+
+# Copyright Oliver Kowalke 2013.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import common ;
+import feature ;
+import indirect ;
+import modules ;
+import os ;
+import path ;
+import testing ;
+import toolset ;
+import ../../config/checks/config : requires ;
+
+project boost/fiber/test
+ : requirements
+ <library>../../test/build//boost_unit_test_framework
+ <library>/boost/context//boost_context
+ <library>/boost/fiber//boost_fiber
+ <library>/boost/thread//boost_thread
+ <target-os>solaris:<linkflags>"-llgrp"
+ <target-os>windows:<define>_WIN32_WINNT=0x0601
+ <toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
+ <toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
+ <link>static
+ <threading>multi
+ <optimization>speed
+ <variant>release
+ ;
+
+
+rule native-impl ( properties * )
+{
+ local result ;
+ if ( <target-os>darwin in $(properties) || <target-os>android in $(properties) )
+ {
+ result = <build>no ;
+ }
+ else if ( ! ( <target-os>windows in $(properties) ) )
+ {
+ result = <context-impl>ucontext ;
+ }
+ else
+ {
+ result = <context-impl>winfib ;
+ }
+ return $(result) ;
+}
+
+
+# tests using assembler API
+test-suite asm :
+[ run test_fiber_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fiber_post_asm ]
+
+[ run test_fiber_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fiber_dispatch_asm ]
+
+[ run test_mutex_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_post_asm ]
+
+[ run test_mutex_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_dispatch_asm ]
+
+[ run test_condition_variable_any_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_variable_any_post_asm ]
+
+[ run test_condition_variable_any_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_variable_any_dispatch_asm ]
+
+[ run test_condition_variable_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_variable_post_asm ]
+
+[ run test_condition_variable_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_variable_dispatch_asm ]
+
+[ run test_barrier_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_barrier_post_asm ]
+
+[ run test_barrier_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_barrier_dispatch_asm ]
+
+[ run test_buffered_channel_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_buffered_channel_post_asm ]
+
+[ run test_buffered_channel_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_buffered_channel_dispatch_asm ]
+
+[ run test_unbuffered_channel_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_unbuffered_channel_post_asm ]
+
+[ run test_unbuffered_channel_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_unbuffered_channel_dispatch_asm ]
+
+[ run test_fss_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fss_post_asm ]
+
+[ run test_fss_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fss_dispatch_asm ]
+
+[ run test_promise_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_promise_post_asm ]
+
+[ run test_promise_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_promise_dispatch_asm ]
+
+[ run test_future_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_post_asm ]
+
+[ run test_future_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_dispatch_asm ]
+
+[ run test_shared_future_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_shared_future_post_asm ]
+
+[ run test_shared_future_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_shared_future_dispatch_asm ]
+
+[ run test_packaged_task_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_packaged_task_post_asm ]
+
+[ run test_packaged_task_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_packaged_task_dispatch_asm ]
+
+[ run test_async_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_async_post_asm ]
+
+[ run test_async_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_async_dispatch_asm ] ;
+
+
+# tests using native API
+test-suite native :
+[ run test_fiber_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fiber_post_native ]
+
+[ run test_fiber_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fiber_dispatch_native ]
+
+[ run test_mutex_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_post_native ]
+
+[ run test_mutex_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_dispatch_native ]
+
+[ run test_condition_variable_any_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_cond_var_any_post_native ]
+
+[ run test_condition_variable_any_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_cond_vare_any_dispatch_native ]
+
+[ run test_condition_variable_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_cond_var_post_native ]
+
+[ run test_condition_variable_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_cond_var_dispatch_native ]
+
+[ run test_barrier_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_barrier_post_native ]
+
+[ run test_barrier_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_barrier_dispatch_native ]
+
+[ run test_buffered_channel_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_buf_channel_post_native ]
+
+[ run test_buffered_channel_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_buf_channel_dispatch_native ]
+
+[ run test_unbuffered_channel_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_unbuf_channel_post_native ]
+
+[ run test_unbuffered_channel_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_unbuf_channel_dispatch_native ]
+
+[ run test_fss_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fss_post_native ]
+
+[ run test_fss_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_fss_dispatch_native ]
+
+[ run test_promise_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_promise_post_native ]
+
+[ run test_promise_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_promise_dispatch_native ]
+
+[ run test_future_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_post_native ]
+
+[ run test_future_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_dispatch_native ]
+
+[ run test_shared_future_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_shared_future_post_native ]
+
+[ run test_shared_future_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_shared_future_dispatch_native ]
+
+[ run test_packaged_task_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_packaged_task_post_native ]
+
+[ run test_packaged_task_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_packaged_task_dispatch_native ]
+
+[ run test_async_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_async_post_native ]
+
+[ run test_async_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_async_dispatch_native ] ;
+
+
+#etra tests using asm API
+test-suite extra-asm :
+[ run test_mutex_mt_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_mt_post_asm ]
+
+[ run test_mutex_mt_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_mt_dispatch_asm ]
+
+[ run test_condition_mt_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_mt_post_asm ]
+
+[ run test_condition_mt_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_mt_dispatch_asm ]
+
+[ run test_future_mt_post.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_mt_post_asm ]
+
+[ run test_future_mt_dispatch.cpp :
+ : :
+ <context-impl>fcontext
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_mt_dispatch_asm ] ;
+
+
+#etra tests using native API
+test-suite extra-native :
+[ run test_mutex_mt_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_mt_post_native ]
+
+[ run test_mutex_mt_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_mutex_mt_dispatch_native ]
+
+[ run test_condition_mt_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_mt_post_native ]
+
+[ run test_condition_mt_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_condition_mt_dispatch_native ]
+
+[ run test_future_mt_post.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_mt_post_native ]
+
+[ run test_future_mt_dispatch.cpp :
+ : :
+ <conditional>@native-impl
+ [ requires cxx11_auto_declarations
+ cxx11_constexpr
+ cxx11_defaulted_functions
+ cxx11_final
+ cxx11_hdr_mutex
+ cxx11_hdr_thread
+ cxx11_hdr_tuple
+ cxx11_lambdas
+ cxx11_noexcept
+ cxx11_nullptr
+ cxx11_rvalue_references
+ cxx11_template_aliases
+ cxx11_thread_local
+ cxx11_variadic_templates ]
+ : test_future_mt_dispatch_native ] ;
+
+
+test-suite minimal :
+ asm native ;
+
+test-suite extra :
+ extra-asm extra-native ;
+
+explicit minmal ;
+explicit extra ;
+
+test-suite full :
+ minimal extra ;
diff --git a/src/boost/libs/fiber/test/test_async_dispatch.cpp b/src/boost/libs/fiber/test/test_async_dispatch.cpp
new file mode 100644
index 00000000..55e050e2
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_async_dispatch.cpp
@@ -0,0 +1,157 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A & operator=( A const&) = delete;
+
+ A( A && other) :
+ value{ other.value } {
+ other.value = 0;
+ }
+
+ A & operator=( A && other) {
+ if ( this == & other) return * this;
+ value = other.value;
+ other.value = 0;
+ return * this;
+ }
+
+ int value{ 0 };
+};
+
+struct X {
+ int value;
+
+ void foo( int i) {
+ value = i;
+ }
+};
+
+void fn1() {
+}
+
+int fn2( int i) {
+ return i;
+}
+
+int & fn3( int & i) {
+ return i;
+}
+
+A fn4( A && a) {
+ return std::forward< A >( a);
+}
+
+void test_async_1() {
+ boost::fibers::future< void > f1 = boost::fibers::async( boost::fibers::launch::dispatch, fn1);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+}
+
+void test_async_2() {
+ int i = 3;
+ boost::fibers::future< int > f1 = boost::fibers::async( boost::fibers::launch::dispatch, fn2, i);
+ BOOST_CHECK( f1.valid() );
+
+ BOOST_CHECK( i == f1.get());
+}
+
+void test_async_3() {
+ int i = 7;
+ boost::fibers::future< int& > f1 = boost::fibers::async( boost::fibers::launch::dispatch, fn3, std::ref( i) );
+ BOOST_CHECK( f1.valid() );
+
+ BOOST_CHECK( & i == & f1.get());
+}
+
+void test_async_4() {
+ A a1;
+ a1.value = 7;
+ boost::fibers::future< A > f1 = boost::fibers::async( boost::fibers::launch::dispatch, fn4, std::move( a1) );
+ BOOST_CHECK( f1.valid() );
+
+ A a2 = f1.get();
+ BOOST_CHECK( 7 == a2.value);
+}
+
+void test_async_5() {
+ X x = {0};
+ BOOST_CHECK( 0 == x.value);
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::dispatch,
+ std::bind( & X::foo, std::ref( x), 3) );
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+ BOOST_CHECK( 3 == x.value);
+}
+
+void test_async_6() {
+ X x = {0};
+ BOOST_CHECK( 0 == x.value);
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::dispatch,
+ std::bind( & X::foo, std::ref( x), std::placeholders::_1), 3);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+ BOOST_CHECK( 3 == x.value);
+}
+
+void test_async_stack_alloc() {
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::dispatch,
+ std::allocator_arg,
+ boost::fibers::fixedsize_stack{},
+ fn1);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+}
+
+void test_async_std_alloc() {
+ struct none {};
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::dispatch,
+ std::allocator_arg,
+ boost::fibers::fixedsize_stack{},
+ std::allocator< none >{},
+ fn1);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: async test suite");
+
+ test->add(BOOST_TEST_CASE(test_async_1));
+ test->add(BOOST_TEST_CASE(test_async_2));
+ test->add(BOOST_TEST_CASE(test_async_3));
+ test->add(BOOST_TEST_CASE(test_async_4));
+ test->add(BOOST_TEST_CASE(test_async_5));
+ test->add(BOOST_TEST_CASE(test_async_6));
+ test->add(BOOST_TEST_CASE(test_async_stack_alloc));
+ test->add(BOOST_TEST_CASE(test_async_std_alloc));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_async_post.cpp b/src/boost/libs/fiber/test/test_async_post.cpp
new file mode 100644
index 00000000..95ab36ed
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_async_post.cpp
@@ -0,0 +1,131 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A & operator=( A const&) = delete;
+
+ A( A && other) :
+ value{ other.value } {
+ other.value = 0;
+ }
+
+ A & operator=( A && other) {
+ if ( this == & other) return * this;
+ value = other.value;
+ other.value = 0;
+ return * this;
+ }
+
+ int value{ 0 };
+};
+
+struct X {
+ int value;
+
+ void foo( int i) {
+ value = i;
+ }
+};
+
+void fn1() {
+}
+
+int fn2( int i) {
+ return i;
+}
+
+int & fn3( int & i) {
+ return i;
+}
+
+A fn4( A && a) {
+ return std::forward< A >( a);
+}
+
+void test_async_1() {
+ boost::fibers::future< void > f1 = boost::fibers::async( boost::fibers::launch::post, fn1);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+}
+
+void test_async_2() {
+ int i = 3;
+ boost::fibers::future< int > f1 = boost::fibers::async( boost::fibers::launch::post, fn2, i);
+ BOOST_CHECK( f1.valid() );
+
+ BOOST_CHECK( i == f1.get());
+}
+
+void test_async_3() {
+ int i = 7;
+ boost::fibers::future< int& > f1 = boost::fibers::async( boost::fibers::launch::post, fn3, std::ref( i) );
+ BOOST_CHECK( f1.valid() );
+
+ BOOST_CHECK( & i == & f1.get());
+}
+
+void test_async_4() {
+ A a1;
+ a1.value = 7;
+ boost::fibers::future< A > f1 = boost::fibers::async( boost::fibers::launch::post, fn4, std::move( a1) );
+ BOOST_CHECK( f1.valid() );
+
+ A a2 = f1.get();
+ BOOST_CHECK( 7 == a2.value);
+}
+
+void test_async_5() {
+ X x = {0};
+ BOOST_CHECK( 0 == x.value);
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::post,
+ std::bind( & X::foo, std::ref( x), 3) );
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+ BOOST_CHECK( 3 == x.value);
+}
+
+void test_async_6() {
+ X x = {0};
+ BOOST_CHECK( 0 == x.value);
+ boost::fibers::future< void > f1 = boost::fibers::async(
+ boost::fibers::launch::post,
+ std::bind( & X::foo, std::ref( x), std::placeholders::_1), 3);
+ BOOST_CHECK( f1.valid() );
+
+ f1.get();
+ BOOST_CHECK( 3 == x.value);
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: async test suite");
+
+ test->add(BOOST_TEST_CASE(test_async_1));
+ test->add(BOOST_TEST_CASE(test_async_2));
+ test->add(BOOST_TEST_CASE(test_async_3));
+ test->add(BOOST_TEST_CASE(test_async_4));
+ test->add(BOOST_TEST_CASE(test_async_5));
+ test->add(BOOST_TEST_CASE(test_async_6));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_barrier_dispatch.cpp b/src/boost/libs/fiber/test/test_barrier_dispatch.cpp
new file mode 100644
index 00000000..8f1716d5
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_barrier_dispatch.cpp
@@ -0,0 +1,71 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <sstream>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int value1 = 0;
+int value2 = 0;
+
+void fn1( boost::fibers::barrier & b) {
+ ++value1;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+}
+
+void fn2( boost::fibers::barrier & b) {
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+}
+
+void test_barrier() {
+ value1 = 0;
+ value2 = 0;
+
+ boost::fibers::barrier b( 2);
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, fn1, std::ref( b) );
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, fn2, std::ref( b) );
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: barrier test suite");
+
+ test->add( BOOST_TEST_CASE( & test_barrier) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_barrier_post.cpp b/src/boost/libs/fiber/test/test_barrier_post.cpp
new file mode 100644
index 00000000..15354dde
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_barrier_post.cpp
@@ -0,0 +1,71 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <sstream>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int value1 = 0;
+int value2 = 0;
+
+void fn1( boost::fibers::barrier & b) {
+ ++value1;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+ boost::this_fiber::yield();
+ ++value1;
+}
+
+void fn2( boost::fibers::barrier & b) {
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+ boost::this_fiber::yield();
+
+ b.wait();
+
+ ++value2;
+ boost::this_fiber::yield();
+ ++value2;
+}
+
+void test_barrier() {
+ value1 = 0;
+ value2 = 0;
+
+ boost::fibers::barrier b( 2);
+ boost::fibers::fiber f1( boost::fibers::launch::post, fn1, std::ref( b) );
+ boost::fibers::fiber f2( boost::fibers::launch::post, fn2, std::ref( b) );
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 5, value1);
+ BOOST_CHECK_EQUAL( 5, value2);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: barrier test suite");
+
+ test->add( BOOST_TEST_CASE( & test_barrier) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_buffered_channel_dispatch.cpp b/src/boost/libs/fiber/test/test_buffered_channel_dispatch.cpp
new file mode 100644
index 00000000..980fdb91
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_buffered_channel_dispatch.cpp
@@ -0,0 +1,531 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 <chrono>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct moveable {
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ other.state = false;
+ value = other.value;
+ other.value = -1;
+ return * this;
+ }
+};
+
+void test_zero_wm() {
+ bool thrown = false;
+ try {
+ boost::fibers::buffered_channel< int > c( 0);
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_push() {
+ boost::fibers::buffered_channel< int > c( 16);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+}
+
+void test_push_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push( 1) );
+}
+
+void test_try_push() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+}
+
+void test_try_push_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_push( 1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.try_push( 2) );
+}
+
+void test_try_push_full() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_push( 1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::full == c.try_push( 1) );
+}
+
+void test_push_wait_for() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_timeout() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_timeout() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop( v2) );
+}
+
+void test_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+ bool thrown = false;
+ try {
+ c.value_pop();
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_value_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&v2](){
+ v2 = c.value_pop();
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_try_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_try_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.try_pop( v2) );
+}
+
+void test_try_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&v2](){
+ while ( boost::fibers::channel_op_status::success != c.try_pop( v2) ) {
+ boost::this_fiber::yield();
+ }
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+}
+
+void test_pop_wait_for_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_timeout() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_for( v, std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_pop_wait_until() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_pop_wait_until_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_timeout() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_until( v,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_wm_1() {
+ boost::fibers::buffered_channel< int > c( 4);
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would block because channel is empty
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 12u, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id1, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id1, ids[3]);
+ BOOST_CHECK_EQUAL( id2, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id2, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id2, ids[9]);
+ BOOST_CHECK_EQUAL( id1, ids[10]);
+ BOOST_CHECK_EQUAL( id2, ids[11]);
+}
+
+void test_wm_2() {
+ boost::fibers::buffered_channel< int > c( 4);
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( (std::size_t)12, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id1, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id1, ids[3]);
+ BOOST_CHECK_EQUAL( id2, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id1, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id2, ids[9]);
+ BOOST_CHECK_EQUAL( id2, ids[10]);
+ BOOST_CHECK_EQUAL( id2, ids[11]);
+}
+
+void test_moveable() {
+ boost::fibers::buffered_channel< moveable > c( 16);
+ moveable m1( 3), m2;
+ BOOST_CHECK( m1.state);
+ BOOST_CHECK_EQUAL( 3, m1.value);
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK_EQUAL( -1, m2.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( std::move( m1) ) );
+ BOOST_CHECK( ! m1.state);
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( m2) );
+ BOOST_CHECK( ! m1.state);
+ BOOST_CHECK_EQUAL( -1, m1.value);
+ BOOST_CHECK( m2.state);
+ BOOST_CHECK_EQUAL( 3, m2.value);
+}
+
+void test_rangefor() {
+ boost::fibers::buffered_channel< int > chan{ 4 };
+ std::vector< int > vec;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&chan]{
+ chan.push( 1);
+ chan.push( 1);
+ chan.push( 2);
+ chan.push( 3);
+ chan.push( 5);
+ chan.push( 8);
+ chan.push( 12);
+ chan.close();
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&vec,&chan]{
+ for ( int value : chan) {
+ vec.push_back( value);
+ }
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, vec[0]);
+ BOOST_CHECK_EQUAL( 1, vec[1]);
+ BOOST_CHECK_EQUAL( 2, vec[2]);
+ BOOST_CHECK_EQUAL( 3, vec[3]);
+ BOOST_CHECK_EQUAL( 5, vec[4]);
+ BOOST_CHECK_EQUAL( 8, vec[5]);
+ BOOST_CHECK_EQUAL( 12, vec[6]);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: buffered_channel test suite");
+
+ test->add( BOOST_TEST_CASE( & test_zero_wm) );
+ test->add( BOOST_TEST_CASE( & test_push) );
+ test->add( BOOST_TEST_CASE( & test_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_push) );
+ test->add( BOOST_TEST_CASE( & test_try_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_push_full) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop) );
+ test->add( BOOST_TEST_CASE( & test_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_value_pop) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_try_pop) );
+ test->add( BOOST_TEST_CASE( & test_try_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_wm_1) );
+ test->add( BOOST_TEST_CASE( & test_wm_2) );
+ test->add( BOOST_TEST_CASE( & test_moveable) );
+ test->add( BOOST_TEST_CASE( & test_rangefor) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_buffered_channel_post.cpp b/src/boost/libs/fiber/test/test_buffered_channel_post.cpp
new file mode 100644
index 00000000..ffc14a7b
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_buffered_channel_post.cpp
@@ -0,0 +1,529 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 <chrono>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct moveable {
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ other.state = false;
+ value = other.value;
+ other.value = -1;
+ return * this;
+ }
+};
+
+void test_zero_wm() {
+ bool thrown = false;
+ try {
+ boost::fibers::buffered_channel< int > c( 0);
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_push() {
+ boost::fibers::buffered_channel< int > c( 16);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+}
+
+void test_push_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push( 1) );
+}
+
+void test_try_push() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+}
+
+void test_try_push_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_push( 1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.try_push( 2) );
+}
+
+void test_try_push_full() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_push( 1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::full == c.try_push( 2) );
+}
+
+void test_push_wait_for() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_timeout() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_for( 2, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_closed() {
+ boost::fibers::buffered_channel< int > c( 2);
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_timeout() {
+ boost::fibers::buffered_channel< int > c( 2);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_until( 2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop( v2) );
+}
+
+void test_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+ bool thrown = false;
+ try {
+ c.value_pop();
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_value_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&v2](){
+ v2 = c.value_pop();
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_try_pop() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_try_pop_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.try_pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.try_pop( v2) );
+}
+
+void test_try_pop_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&v2](){
+ while ( boost::fibers::channel_op_status::success != c.try_pop( v2) ) {
+ boost::this_fiber::yield();
+ }
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+}
+
+void test_pop_wait_for_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_timeout() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_for( v, std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_pop_wait_until() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_closed() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_pop_wait_until_success() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_timeout() {
+ boost::fibers::buffered_channel< int > c( 16);
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_until( v,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_wm_1() {
+ boost::fibers::buffered_channel< int > c( 4);
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would block because channel is empty
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( (std::size_t)12, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id1, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id1, ids[3]);
+ BOOST_CHECK_EQUAL( id2, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id2, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id2, ids[9]);
+ BOOST_CHECK_EQUAL( id1, ids[10]);
+ BOOST_CHECK_EQUAL( id2, ids[11]);
+}
+
+void test_wm_2() {
+ boost::fibers::buffered_channel< int > c( 8);
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( (std::size_t)12, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id1, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id1, ids[3]);
+ BOOST_CHECK_EQUAL( id1, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id2, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id2, ids[9]);
+ BOOST_CHECK_EQUAL( id2, ids[10]);
+ BOOST_CHECK_EQUAL( id2, ids[11]);
+}
+
+void test_moveable() {
+ boost::fibers::buffered_channel< moveable > c( 16);
+ moveable m1( 3), m2;
+ BOOST_CHECK( m1.state);
+ BOOST_CHECK_EQUAL( 3, m1.value);
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK_EQUAL( -1, m2.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( std::move( m1) ) );
+ BOOST_CHECK( ! m1.state);
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( m2) );
+ BOOST_CHECK( ! m1.state);
+ BOOST_CHECK_EQUAL( -1, m1.value);
+ BOOST_CHECK( m2.state);
+ BOOST_CHECK_EQUAL( 3, m2.value);
+}
+
+void test_rangefor() {
+ boost::fibers::buffered_channel< int > chan{ 2 };
+ std::vector< int > vec;
+ boost::fibers::fiber f1([&chan]{
+ chan.push( 1);
+ chan.push( 1);
+ chan.push( 2);
+ chan.push( 3);
+ chan.push( 5);
+ chan.push( 8);
+ chan.push( 12);
+ chan.close();
+ });
+ boost::fibers::fiber f2([&vec,&chan]{
+ for ( int value : chan) {
+ vec.push_back( value);
+ }
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, vec[0]);
+ BOOST_CHECK_EQUAL( 1, vec[1]);
+ BOOST_CHECK_EQUAL( 2, vec[2]);
+ BOOST_CHECK_EQUAL( 3, vec[3]);
+ BOOST_CHECK_EQUAL( 5, vec[4]);
+ BOOST_CHECK_EQUAL( 8, vec[5]);
+ BOOST_CHECK_EQUAL( 12, vec[6]);
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: buffered_channel test suite");
+
+ test->add( BOOST_TEST_CASE( & test_zero_wm) );
+ test->add( BOOST_TEST_CASE( & test_push) );
+ test->add( BOOST_TEST_CASE( & test_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_push) );
+ test->add( BOOST_TEST_CASE( & test_try_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_push_full) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop) );
+ test->add( BOOST_TEST_CASE( & test_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_value_pop) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_try_pop) );
+ test->add( BOOST_TEST_CASE( & test_try_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_try_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_wm_1) );
+ test->add( BOOST_TEST_CASE( & test_wm_2) );
+ test->add( BOOST_TEST_CASE( & test_moveable) );
+ test->add( BOOST_TEST_CASE( & test_rangefor) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_mt_dispatch.cpp b/src/boost/libs/fiber/test/test_condition_mt_dispatch.cpp
new file mode 100644
index 00000000..e57fd087
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_mt_dispatch.cpp
@@ -0,0 +1,164 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/atomic.hpp>
+#include <boost/bind.hpp>
+#include <boost/chrono.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef boost::chrono::milliseconds ms;
+
+boost::atomic< int > value1;
+
+void wait_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ cond.wait( lk, [&flag](){ return flag; });
+ ++value1;
+}
+
+void notify_one_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ flag = true;
+ lk.unlock();
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ flag = true;
+ lk.unlock();
+ cond.notify_all();
+}
+
+void fn1( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void fn2( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void fn3( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::dispatch,
+ notify_all_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void test_one_waiter_notify_one() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::barrier b( 2);
+
+ bool flag = false;
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ BOOST_CHECK( 0 == value1);
+
+ boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t2(std::bind( fn2, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+
+ t1.join();
+ t2.join();
+
+ BOOST_CHECK( 1 == value1);
+ }
+}
+
+void test_two_waiter_notify_all() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::barrier b( 3);
+
+ bool flag = false;
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ BOOST_CHECK( 0 == value1);
+
+ boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t2(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t3(std::bind( fn3, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+
+ t1.join();
+ t2.join();
+ t3.join();
+
+ BOOST_CHECK( 2 == value1);
+ }
+}
+
+void test_dummy() {
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition_variable test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+#else
+ test->add( BOOST_TEST_CASE( & test_dummy) );
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_mt_post.cpp b/src/boost/libs/fiber/test/test_condition_mt_post.cpp
new file mode 100644
index 00000000..b85647eb
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_mt_post.cpp
@@ -0,0 +1,164 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/atomic.hpp>
+#include <boost/bind.hpp>
+#include <boost/chrono.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef boost::chrono::milliseconds ms;
+
+boost::atomic< int > value1;
+
+void wait_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ cond.wait( lk, [&flag](){ return flag; });
+ ++value1;
+}
+
+void notify_one_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ flag = true;
+ lk.unlock();
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ b.wait();
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ flag = true;
+ lk.unlock();
+ cond.notify_all();
+}
+
+void fn1( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void fn2( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void fn3( boost::barrier & b,
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond,
+ bool & flag) {
+ boost::fibers::fiber(
+ boost::fibers::launch::post,
+ notify_all_fn,
+ std::ref( b),
+ std::ref( mtx),
+ std::ref( cond),
+ std::ref( flag) ).join();
+}
+
+void test_one_waiter_notify_one() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::barrier b( 2);
+
+ bool flag = false;
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ BOOST_CHECK( 0 == value1);
+
+ boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t2(std::bind( fn2, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+
+ t1.join();
+ t2.join();
+
+ BOOST_CHECK( 1 == value1);
+ }
+}
+
+void test_two_waiter_notify_all() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::barrier b( 3);
+
+ bool flag = false;
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ BOOST_CHECK( 0 == value1);
+
+ boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t2(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+ boost::thread t3(std::bind( fn3, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
+
+ t1.join();
+ t2.join();
+ t3.join();
+
+ BOOST_CHECK( 2 == value1);
+ }
+}
+
+void test_dummy() {
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition_variable test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+#else
+ test->add( BOOST_TEST_CASE( & test_dummy) );
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_variable_any_dispatch.cpp b/src/boost/libs/fiber/test/test_condition_variable_any_dispatch.cpp
new file mode 100644
index 00000000..e227fd45
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_variable_any_dispatch.cpp
@@ -0,0 +1,501 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+
+inline
+std::chrono::system_clock::time_point delay(int secs, int msecs = 0, int /*nsecs*/ = 0) {
+ std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
+ t += std::chrono::seconds( secs);
+ t += std::chrono::milliseconds( msecs);
+ //t += std::chrono::nanoseconds( nsecs);
+
+ return t;
+}
+
+struct condition_test_data {
+ condition_test_data() : notified(0), awoken(0) { }
+
+ boost::fibers::mutex mutex;
+ boost::fibers::condition_variable_any cond;
+ int notified;
+ int awoken;
+};
+
+void condition_test_fiber(condition_test_data* data) {
+ try {
+ data->mutex.lock();
+ while (!(data->notified > 0))
+ data->cond.wait(data->mutex);
+ data->awoken++;
+ } catch ( ... ) {
+ }
+ data->mutex.unlock();
+}
+
+struct cond_predicate {
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
+
+ bool operator()() { return _var == _val; }
+
+ int& _var;
+ int _val;
+private:
+ void operator=(cond_predicate&);
+
+};
+
+void notify_one_fn( boost::fibers::condition_variable_any & cond) {
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fibers::condition_variable_any & cond) {
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable_any & cond) {
+ mtx.lock();
+ cond.wait( mtx);
+ ++value1;
+ mtx.unlock();
+}
+
+void test_one_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 1, value1);
+}
+
+void test_two_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 1, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+
+ BOOST_CHECK_EQUAL( 2, value1);
+}
+
+void test_two_waiter_notify_all() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::dispatch,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 2, value1);
+
+ boost::fibers::fiber f5(
+ boost::fibers::launch::dispatch,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 2, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+int test1 = 0;
+int test2 = 0;
+
+int runs = 0;
+
+void fn1( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ while (test2 == 0) {
+ cv.wait(m);
+ }
+ BOOST_CHECK(test2 != 0);
+ m.unlock();
+}
+
+void fn2( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();
+ std::chrono::system_clock::time_point t = t0 + ms(250);
+ int count=0;
+ while (test2 == 0 && cv.wait_until(m, t) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+class Pred {
+ int & i_;
+
+public:
+ explicit Pred(int& i) :
+ i_(i)
+ {}
+
+ bool operator()()
+ { return i_ != 0; }
+};
+
+void fn3( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ std::chrono::steady_clock::time_point t = t0 + ms(250);
+ bool r = cv.wait_until(m, t, Pred(test2));
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ BOOST_CHECK(r);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(250+100));
+ BOOST_CHECK(test2 == 0);
+ BOOST_CHECK(!r);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void fn4( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ while (test2 == 0 && cv.wait_for(m, ms(250)) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void fn5( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ cv.wait_for(m, ms(250), Pred(test2));
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250+1000));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void do_test_condition_wait() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn1, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+}
+
+void test_condition_wait() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait).join();
+ do_test_condition_wait();
+}
+
+void do_test_condition_wait_until() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until).join();
+ do_test_condition_wait_until();
+}
+
+void do_test_condition_wait_until_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until_pred() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until_pred).join();
+ do_test_condition_wait_until_pred();
+}
+
+void do_test_condition_wait_for() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for).join();
+ do_test_condition_wait_for();
+}
+
+void do_test_condition_wait_for_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for_pred() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for_pred).join();
+ do_test_condition_wait_for_pred();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: condition_variable_any test suite");
+
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until_pred) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for_pred) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_variable_any_post.cpp b/src/boost/libs/fiber/test/test_condition_variable_any_post.cpp
new file mode 100644
index 00000000..da6d882a
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_variable_any_post.cpp
@@ -0,0 +1,501 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+
+inline
+std::chrono::system_clock::time_point delay(int secs, int msecs=0, int /*nsecs*/=0) {
+ std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
+ t += std::chrono::seconds( secs);
+ t += std::chrono::milliseconds( msecs);
+ //t += std::chrono::nanoseconds( nsecs);
+
+ return t;
+}
+
+struct condition_test_data {
+ condition_test_data() : notified(0), awoken(0) { }
+
+ boost::fibers::mutex mutex;
+ boost::fibers::condition_variable_any cond;
+ int notified;
+ int awoken;
+};
+
+void condition_test_fiber(condition_test_data* data) {
+ try {
+ data->mutex.lock();
+ while (!(data->notified > 0))
+ data->cond.wait(data->mutex);
+ data->awoken++;
+ } catch ( ... ) {
+ }
+ data->mutex.unlock();
+}
+
+struct cond_predicate {
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
+
+ bool operator()() { return _var == _val; }
+
+ int& _var;
+ int _val;
+private:
+ void operator=(cond_predicate&);
+
+};
+
+void notify_one_fn( boost::fibers::condition_variable_any & cond) {
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fibers::condition_variable_any & cond) {
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable_any & cond) {
+ mtx.lock();
+ cond.wait( mtx);
+ ++value1;
+ mtx.unlock();
+}
+
+void test_one_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 1, value1);
+}
+
+void test_two_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+
+ BOOST_CHECK_EQUAL( 2, value1);
+}
+
+void test_two_waiter_notify_all() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable_any cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::post,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f5(
+ boost::fibers::launch::post,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+int test1 = 0;
+int test2 = 0;
+
+int runs = 0;
+
+void fn1( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ while (test2 == 0) {
+ cv.wait(m);
+ }
+ BOOST_CHECK(test2 != 0);
+ m.unlock();
+}
+
+void fn2( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();
+ std::chrono::system_clock::time_point t = t0 + ms(250);
+ int count=0;
+ while (test2 == 0 && cv.wait_until(m, t) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+class Pred {
+ int & i_;
+
+public:
+ explicit Pred(int& i) :
+ i_(i)
+ {}
+
+ bool operator()()
+ { return i_ != 0; }
+};
+
+void fn3( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ std::chrono::steady_clock::time_point t = t0 + ms(250);
+ bool r = cv.wait_until(m, t, Pred(test2));
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ BOOST_CHECK(r);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(250+100));
+ BOOST_CHECK(test2 == 0);
+ BOOST_CHECK(!r);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void fn4( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ while (test2 == 0 && cv.wait_for(m, ms(250)) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void fn5( boost::fibers::mutex & m, boost::fibers::condition_variable_any & cv) {
+ m.lock();
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ cv.wait_for(m, ms(250), Pred(test2));
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250+1000));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+ m.unlock();
+}
+
+void do_test_condition_wait() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn1, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+}
+
+void test_condition_wait() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait).join();
+ do_test_condition_wait();
+}
+
+void do_test_condition_wait_until() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_until).join();
+ do_test_condition_wait_until();
+}
+
+void do_test_condition_wait_until_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until_pred() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_until_pred).join();
+ do_test_condition_wait_until_pred();
+}
+
+void do_test_condition_wait_for() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_for).join();
+ do_test_condition_wait_for();
+}
+
+void do_test_condition_wait_for_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable_any cv;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ m.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ m.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(m);
+ BOOST_CHECK(test1 != 0);
+ m.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for_pred() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_for_pred).join();
+ do_test_condition_wait_for_pred();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: condition_variable_any test suite");
+
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until_pred) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for_pred) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_variable_dispatch.cpp b/src/boost/libs/fiber/test/test_condition_variable_dispatch.cpp
new file mode 100644
index 00000000..dc5e00fe
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_variable_dispatch.cpp
@@ -0,0 +1,495 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+
+inline
+std::chrono::system_clock::time_point delay(int secs, int msecs = 0, int /*nsecs*/ = 0) {
+ std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
+ t += std::chrono::seconds( secs);
+ t += std::chrono::milliseconds( msecs);
+ //t += std::chrono::nanoseconds( nsecs);
+
+ return t;
+}
+
+struct condition_test_data {
+ condition_test_data() : notified(0), awoken(0) { }
+
+ boost::fibers::mutex mutex;
+ boost::fibers::condition_variable cond;
+ int notified;
+ int awoken;
+};
+
+void condition_test_fiber(condition_test_data* data) {
+ std::unique_lock<boost::fibers::mutex> lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
+ while (!(data->notified > 0))
+ data->cond.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ data->awoken++;
+}
+
+struct cond_predicate {
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
+
+ bool operator()() { return _var == _val; }
+
+ int& _var;
+ int _val;
+private:
+ void operator=(cond_predicate&);
+
+};
+
+void notify_one_fn( boost::fibers::condition_variable & cond) {
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fibers::condition_variable & cond) {
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond) {
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ cond.wait( lk);
+ ++value1;
+}
+
+void test_one_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 1, value1);
+}
+
+void test_two_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::dispatch,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 1, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+
+ BOOST_CHECK_EQUAL( 2, value1);
+}
+
+void test_two_waiter_notify_all() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::dispatch,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::dispatch,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 2, value1);
+
+ boost::fibers::fiber f5(
+ boost::fibers::launch::dispatch,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 2, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+int test1 = 0;
+int test2 = 0;
+
+int runs = 0;
+
+void fn1( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ while (test2 == 0) {
+ cv.wait(lk);
+ }
+ BOOST_CHECK(test2 != 0);
+}
+
+void fn2( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();
+ std::chrono::system_clock::time_point t = t0 + ms(250);
+ int count=0;
+ while (test2 == 0 && cv.wait_until(lk, t) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+class Pred {
+ int & i_;
+
+public:
+ explicit Pred(int& i) :
+ i_(i)
+ {}
+
+ bool operator()()
+ { return i_ != 0; }
+};
+
+void fn3( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ std::chrono::steady_clock::time_point t = t0 + ms(250);
+ bool r = cv.wait_until(lk, t, Pred(test2));
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ BOOST_CHECK(r);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(250+100));
+ BOOST_CHECK(test2 == 0);
+ BOOST_CHECK(!r);
+ }
+ ++runs;
+}
+
+void fn4( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ while (test2 == 0 && cv.wait_for(lk, ms(250)) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+void fn5( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ cv.wait_for(lk, ms(250), Pred(test2));
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250+1000));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+void do_test_condition_wait() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn1, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+}
+
+void test_condition_wait() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait).join();
+ do_test_condition_wait();
+}
+
+void do_test_condition_wait_until() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until).join();
+ do_test_condition_wait_until();
+}
+
+void do_test_condition_wait_until_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until_pred() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until_pred).join();
+ do_test_condition_wait_until_pred();
+}
+
+void do_test_condition_wait_for() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for).join();
+ do_test_condition_wait_for();
+}
+
+void do_test_condition_wait_for_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for_pred() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for_pred).join();
+ do_test_condition_wait_for_pred();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: condition_variable test suite");
+
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until_pred) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for_pred) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_condition_variable_post.cpp b/src/boost/libs/fiber/test/test_condition_variable_post.cpp
new file mode 100644
index 00000000..3f043a7b
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_condition_variable_post.cpp
@@ -0,0 +1,495 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+
+inline
+std::chrono::system_clock::time_point delay(int secs, int msecs = 0, int /*nsecs*/ = 0) {
+ std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
+ t += std::chrono::seconds( secs);
+ t += std::chrono::milliseconds( msecs);
+ //t += std::chrono::nanoseconds( nsecs);
+
+ return t;
+}
+
+struct condition_test_data {
+ condition_test_data() : notified(0), awoken(0) { }
+
+ boost::fibers::mutex mutex;
+ boost::fibers::condition_variable cond;
+ int notified;
+ int awoken;
+};
+
+void condition_test_fiber(condition_test_data* data) {
+ std::unique_lock<boost::fibers::mutex> lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
+ while (!(data->notified > 0))
+ data->cond.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ data->awoken++;
+}
+
+struct cond_predicate {
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
+
+ bool operator()() { return _var == _val; }
+
+ int& _var;
+ int _val;
+private:
+ void operator=(cond_predicate&);
+
+};
+
+void notify_one_fn( boost::fibers::condition_variable & cond) {
+ cond.notify_one();
+}
+
+void notify_all_fn( boost::fibers::condition_variable & cond) {
+ cond.notify_all();
+}
+
+void wait_fn(
+ boost::fibers::mutex & mtx,
+ boost::fibers::condition_variable & cond) {
+ std::unique_lock< boost::fibers::mutex > lk( mtx);
+ cond.wait( lk);
+ ++value1;
+}
+
+void test_one_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+
+ BOOST_CHECK_EQUAL( 1, value1);
+}
+
+void test_two_waiter_notify_one() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::post,
+ notify_one_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+
+ BOOST_CHECK_EQUAL( 2, value1);
+}
+
+void test_two_waiter_notify_all() {
+ value1 = 0;
+ boost::fibers::mutex mtx;
+ boost::fibers::condition_variable cond;
+
+ boost::fibers::fiber f1(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f2(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f3(
+ boost::fibers::launch::post,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f4(
+ boost::fibers::launch::post,
+ wait_fn,
+ std::ref( mtx),
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ boost::fibers::fiber f5(
+ boost::fibers::launch::post,
+ notify_all_fn,
+ std::ref( cond) );
+ BOOST_CHECK_EQUAL( 0, value1);
+
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+int test1 = 0;
+int test2 = 0;
+
+int runs = 0;
+
+void fn1( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ while (test2 == 0) {
+ cv.wait(lk);
+ }
+ BOOST_CHECK(test2 != 0);
+}
+
+void fn2( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();
+ std::chrono::system_clock::time_point t = t0 + ms(250);
+ int count=0;
+ while (test2 == 0 && cv.wait_until(lk, t) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+class Pred {
+ int & i_;
+
+public:
+ explicit Pred(int& i) :
+ i_(i)
+ {}
+
+ bool operator()()
+ { return i_ != 0; }
+};
+
+void fn3( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ std::chrono::steady_clock::time_point t = t0 + ms(250);
+ bool r = cv.wait_until(lk, t, Pred(test2));
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ BOOST_CHECK(r);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(250+100));
+ BOOST_CHECK(test2 == 0);
+ BOOST_CHECK(!r);
+ }
+ ++runs;
+}
+
+void fn4( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ while (test2 == 0 && cv.wait_for(lk, ms(250)) == boost::fibers::cv_status::no_timeout)
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100+1000));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+void fn5( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ BOOST_CHECK(test2 == 0);
+ test1 = 1;
+ cv.notify_one();
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ int count=0;
+ cv.wait_for(lk, ms(250), Pred(test2));
+ count++;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ if (runs == 0) {
+ BOOST_CHECK(t1 - t0 < ms(250+1000));
+ BOOST_CHECK(test2 != 0);
+ } else {
+ BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+100));
+ BOOST_CHECK(test2 == 0);
+ }
+ ++runs;
+}
+
+void do_test_condition_wait() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn1, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+}
+
+void test_condition_wait() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait).join();
+ do_test_condition_wait();
+}
+
+void do_test_condition_wait_until() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn2, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_until).join();
+ do_test_condition_wait_until();
+}
+
+void do_test_condition_wait_until_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_until_pred() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_until_pred).join();
+ do_test_condition_wait_until_pred();
+}
+
+void do_test_condition_wait_for() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_for).join();
+ do_test_condition_wait_for();
+}
+
+void do_test_condition_wait_for_pred() {
+ test1 = 0;
+ test2 = 0;
+ runs = 0;
+
+ boost::fibers::mutex m;
+ boost::fibers::condition_variable cv;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ test2 = 1;
+ lk.unlock();
+ cv.notify_one();
+ f.join();
+ }
+ test1 = 0;
+ test2 = 0;
+ {
+ std::unique_lock< boost::fibers::mutex > lk( m);
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( m), std::ref( cv) );
+ BOOST_CHECK(test1 == 0);
+ while (test1 == 0)
+ cv.wait(lk);
+ BOOST_CHECK(test1 != 0);
+ lk.unlock();
+ f.join();
+ }
+}
+
+void test_condition_wait_for_pred() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_condition_wait_for_pred).join();
+ do_test_condition_wait_for_pred();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: condition_variable test suite");
+
+ test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) );
+ test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_until_pred) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_condition_wait_for_pred) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_fiber_dispatch.cpp b/src/boost/libs/fiber/test/test_fiber_dispatch.cpp
new file mode 100644
index 00000000..1126b001
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_fiber_dispatch.cpp
@@ -0,0 +1,440 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <mutex>
+#include <sstream>
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int value1 = 0;
+std::string value2 = "";
+
+struct X {
+ int value;
+
+ void foo( int i) {
+ value = i;
+ }
+};
+
+class copyable {
+public:
+ bool state;
+ int value;
+
+ copyable() :
+ state( false),
+ value( -1) {
+ }
+
+ copyable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ void operator()() {
+ value1 = value;
+ }
+};
+
+class moveable {
+public:
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ value = other.value;
+ other.state = false;
+ other.value = -1;
+ return * this;
+ }
+
+ moveable( moveable const& other) = delete;
+ moveable & operator=( moveable const& other) = delete;
+
+ void operator()() {
+ value1 = value;
+ }
+};
+
+class detachable {
+private:
+ int alive_count_;
+
+public:
+ static int alive_count;
+ static bool was_running;
+
+ detachable() :
+ alive_count_( 1) {
+ ++alive_count;
+ }
+
+ detachable( detachable const& g) :
+ alive_count_( g.alive_count_) {
+ ++alive_count;
+ }
+
+ ~detachable() {
+ alive_count_ = 0;
+ --alive_count;
+ }
+
+ void operator()() {
+ BOOST_CHECK_EQUAL(1, alive_count_);
+ was_running = true;
+ }
+};
+
+int detachable::alive_count = 0;
+bool detachable::was_running = false;
+
+void fn1() {
+ value1 = 1;
+}
+
+void fn2( int i, std::string const& s) {
+ value1 = i;
+ value2 = s;
+}
+
+void fn3( int & i) {
+ i = 1;
+ boost::this_fiber::yield();
+ i = 1;
+ boost::this_fiber::yield();
+ i = 2;
+ boost::this_fiber::yield();
+ i = 3;
+ boost::this_fiber::yield();
+ i = 5;
+ boost::this_fiber::yield();
+ i = 8;
+}
+
+void fn4() {
+ boost::this_fiber::yield();
+}
+
+void fn5() {
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fn4);
+ BOOST_CHECK( f.joinable() );
+ f.join();
+ BOOST_CHECK( ! f.joinable() );
+}
+
+void test_scheduler_dtor() {
+ boost::fibers::context * ctx(
+ boost::fibers::context::active() );
+ (void)ctx;
+}
+
+void test_join_fn() {
+ {
+ value1 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fn1);
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 1);
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fn2, 3, "abc");
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_memfn() {
+ X x = {0};
+ BOOST_CHECK_EQUAL( x.value, 0);
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & X::foo, & x, 3).join();
+ BOOST_CHECK_EQUAL( x.value, 3);
+}
+
+void test_join_copyable() {
+ value1 = 0;
+ copyable cp( 3);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK_EQUAL( value1, 0);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, cp);
+ f.join();
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK_EQUAL( value1, 3);
+}
+
+void test_join_moveable() {
+ value1 = 0;
+ moveable mv( 7);
+ BOOST_CHECK( mv.state);
+ BOOST_CHECK_EQUAL( value1, 0);
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, std::move( mv) );
+ f.join();
+ BOOST_CHECK( ! mv.state);
+ BOOST_CHECK_EQUAL( value1, 7);
+}
+
+void test_join_lambda() {
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::dispatch, [i,abc]() {
+ value1 = i;
+ value2 = abc;
+ });
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::dispatch, [](int i, std::string const& abc) {
+ value1 = i;
+ value2 = abc;
+ },
+ i, abc);
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_bind() {
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::dispatch, std::bind(
+ [i,abc]() {
+ value1 = i;
+ value2 = abc;
+ }
+ ));
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::dispatch, std::bind(
+ [](std::string & str) {
+ value1 = 3;
+ value2 = str;
+ },
+ abc
+ ));
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::dispatch, std::bind(
+ []( std::string & str) {
+ value1 = 3;
+ value2 = str;
+ },
+ std::placeholders::_1
+ ),
+ std::ref( abc) );
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_in_fiber() {
+ // spawn fiber f
+ // f spawns an new fiber f' in its fiber-fn
+ // f' yields in its fiber-fn
+ // f joins s' and gets suspended (waiting on s')
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fn5);
+ BOOST_CHECK( f.joinable() );
+ // join() resumes f + f' which completes
+ f.join();
+ BOOST_CHECK( ! f.joinable() );
+}
+
+void test_move_fiber() {
+ boost::fibers::fiber f1;
+ BOOST_CHECK( ! f1.joinable() );
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, fn1);
+ BOOST_CHECK( f2.joinable() );
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+ f1.join();
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+}
+
+void test_id() {
+ boost::fibers::fiber f1;
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, fn1);
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( f2.joinable() );
+
+ BOOST_CHECK_EQUAL( boost::fibers::fiber::id(), f1.get_id() );
+ BOOST_CHECK( boost::fibers::fiber::id() != f2.get_id() );
+
+ boost::fibers::fiber f3( boost::fibers::launch::dispatch, fn1);
+ BOOST_CHECK( f2.get_id() != f3.get_id() );
+
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+
+ BOOST_CHECK( boost::fibers::fiber::id() != f1.get_id() );
+ BOOST_CHECK_EQUAL( boost::fibers::fiber::id(), f2.get_id() );
+
+ BOOST_CHECK( ! f2.joinable() );
+
+ f1.join();
+ f3.join();
+}
+
+void test_yield() {
+ int v1 = 0, v2 = 0;
+ BOOST_CHECK_EQUAL( 0, v1);
+ BOOST_CHECK_EQUAL( 0, v2);
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, fn3, std::ref( v1) );
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, fn3, std::ref( v2) );
+ f1.join();
+ f2.join();
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+ BOOST_CHECK_EQUAL( 8, v1);
+ BOOST_CHECK_EQUAL( 8, v2);
+}
+
+void test_sleep_for() {
+ typedef std::chrono::system_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_for(ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the fiber system switches the fiber
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+}
+
+void test_sleep_until() {
+ {
+ typedef std::chrono::steady_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_until(t0 + ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+ }
+ {
+ typedef std::chrono::system_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_until(t0 + ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+ }
+}
+
+void do_wait( boost::fibers::barrier* b) {
+ b->wait();
+}
+
+void test_detach() {
+ {
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, (detachable()) );
+ BOOST_CHECK( f.joinable() );
+ f.detach();
+ BOOST_CHECK( ! f.joinable() );
+ boost::this_fiber::sleep_for( std::chrono::milliseconds(250) );
+ BOOST_CHECK( detachable::was_running);
+ BOOST_CHECK_EQUAL( 0, detachable::alive_count);
+ }
+ {
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, (detachable()) );
+ BOOST_CHECK( f.joinable() );
+ boost::this_fiber::yield();
+ f.detach();
+ BOOST_CHECK( ! f.joinable() );
+ boost::this_fiber::sleep_for( std::chrono::milliseconds(250) );
+ BOOST_CHECK( detachable::was_running);
+ BOOST_CHECK_EQUAL( 0, detachable::alive_count);
+ }
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: fiber test suite");
+
+ test->add( BOOST_TEST_CASE( & test_scheduler_dtor) );
+ test->add( BOOST_TEST_CASE( & test_join_fn) );
+ test->add( BOOST_TEST_CASE( & test_join_memfn) );
+ test->add( BOOST_TEST_CASE( & test_join_copyable) );
+ test->add( BOOST_TEST_CASE( & test_join_moveable) );
+ test->add( BOOST_TEST_CASE( & test_join_lambda) );
+ test->add( BOOST_TEST_CASE( & test_join_bind) );
+ test->add( BOOST_TEST_CASE( & test_join_in_fiber) );
+ test->add( BOOST_TEST_CASE( & test_move_fiber) );
+ test->add( BOOST_TEST_CASE( & test_yield) );
+ test->add( BOOST_TEST_CASE( & test_sleep_for) );
+ test->add( BOOST_TEST_CASE( & test_sleep_until) );
+ test->add( BOOST_TEST_CASE( & test_detach) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_fiber_post.cpp b/src/boost/libs/fiber/test/test_fiber_post.cpp
new file mode 100644
index 00000000..01a7e74c
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_fiber_post.cpp
@@ -0,0 +1,440 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <mutex>
+#include <sstream>
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int value1 = 0;
+std::string value2 = "";
+
+struct X {
+ int value;
+
+ void foo( int i) {
+ value = i;
+ }
+};
+
+class copyable {
+public:
+ bool state;
+ int value;
+
+ copyable() :
+ state( false),
+ value( -1) {
+ }
+
+ copyable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ void operator()() {
+ value1 = value;
+ }
+};
+
+class moveable {
+public:
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ value = other.value;
+ other.state = false;
+ other.value = -1;
+ return * this;
+ }
+
+ moveable( moveable const& other) = delete;
+ moveable & operator=( moveable const& other) = delete;
+
+ void operator()() {
+ value1 = value;
+ }
+};
+
+class detachable {
+private:
+ int alive_count_;
+
+public:
+ static int alive_count;
+ static bool was_running;
+
+ detachable() :
+ alive_count_( 1) {
+ ++alive_count;
+ }
+
+ detachable( detachable const& g) :
+ alive_count_( g.alive_count_) {
+ ++alive_count;
+ }
+
+ ~detachable() {
+ alive_count_ = 0;
+ --alive_count;
+ }
+
+ void operator()() {
+ BOOST_CHECK_EQUAL(1, alive_count_);
+ was_running = true;
+ }
+};
+
+int detachable::alive_count = 0;
+bool detachable::was_running = false;
+
+void fn1() {
+ value1 = 1;
+}
+
+void fn2( int i, std::string const& s) {
+ value1 = i;
+ value2 = s;
+}
+
+void fn3( int & i) {
+ i = 1;
+ boost::this_fiber::yield();
+ i = 1;
+ boost::this_fiber::yield();
+ i = 2;
+ boost::this_fiber::yield();
+ i = 3;
+ boost::this_fiber::yield();
+ i = 5;
+ boost::this_fiber::yield();
+ i = 8;
+}
+
+void fn4() {
+ boost::this_fiber::yield();
+}
+
+void fn5() {
+ boost::fibers::fiber f( boost::fibers::launch::post, fn4);
+ BOOST_CHECK( f.joinable() );
+ f.join();
+ BOOST_CHECK( ! f.joinable() );
+}
+
+void test_scheduler_dtor() {
+ boost::fibers::context * ctx(
+ boost::fibers::context::active() );
+ (void)ctx;
+}
+
+void test_join_fn() {
+ {
+ value1 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, fn1);
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 1);
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ boost::fibers::fiber f( boost::fibers::launch::post, fn2, 3, "abc");
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_memfn() {
+ X x = {0};
+ BOOST_CHECK_EQUAL( x.value, 0);
+ boost::fibers::fiber( boost::fibers::launch::post, & X::foo, & x, 3).join();
+ BOOST_CHECK_EQUAL( x.value, 3);
+}
+
+void test_join_copyable() {
+ value1 = 0;
+ copyable cp( 3);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK_EQUAL( value1, 0);
+ boost::fibers::fiber f( boost::fibers::launch::post, cp);
+ f.join();
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK_EQUAL( value1, 3);
+}
+
+void test_join_moveable() {
+ value1 = 0;
+ moveable mv( 7);
+ BOOST_CHECK( mv.state);
+ BOOST_CHECK_EQUAL( value1, 0);
+ boost::fibers::fiber f( boost::fibers::launch::post, std::move( mv) );
+ f.join();
+ BOOST_CHECK( ! mv.state);
+ BOOST_CHECK_EQUAL( value1, 7);
+}
+
+void test_join_lambda() {
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::post, [i,abc]() {
+ value1 = i;
+ value2 = abc;
+ });
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::post, [](int i, std::string const& abc) {
+ value1 = i;
+ value2 = abc;
+ },
+ i, abc);
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_bind() {
+ {
+ value1 = 0;
+ value2 = "";
+ int i = 3;
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::post, std::bind(
+ [i,abc]() {
+ value1 = i;
+ value2 = abc;
+ }
+ ));
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::post, std::bind(
+ [](std::string & str) {
+ value1 = 3;
+ value2 = str;
+ },
+ abc
+ ));
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+ {
+ value1 = 0;
+ value2 = "";
+ std::string abc("abc");
+ boost::fibers::fiber f(
+ boost::fibers::launch::post, std::bind(
+ []( std::string & str) {
+ value1 = 3;
+ value2 = str;
+ },
+ std::placeholders::_1
+ ),
+ std::ref( abc) );
+ f.join();
+ BOOST_CHECK_EQUAL( value1, 3);
+ BOOST_CHECK_EQUAL( value2, "abc");
+ }
+}
+
+void test_join_in_fiber() {
+ // spawn fiber f
+ // f spawns an new fiber f' in its fiber-fn
+ // f' yields in its fiber-fn
+ // f joins s' and gets suspended (waiting on s')
+ boost::fibers::fiber f( boost::fibers::launch::post, fn5);
+ BOOST_CHECK( f.joinable() );
+ // join() resumes f + f' which completes
+ f.join();
+ BOOST_CHECK( ! f.joinable() );
+}
+
+void test_move_fiber() {
+ boost::fibers::fiber f1;
+ BOOST_CHECK( ! f1.joinable() );
+ boost::fibers::fiber f2( boost::fibers::launch::post, fn1);
+ BOOST_CHECK( f2.joinable() );
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+ f1.join();
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+}
+
+void test_id() {
+ boost::fibers::fiber f1;
+ boost::fibers::fiber f2( boost::fibers::launch::post, fn1);
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( f2.joinable() );
+
+ BOOST_CHECK_EQUAL( boost::fibers::fiber::id(), f1.get_id() );
+ BOOST_CHECK( boost::fibers::fiber::id() != f2.get_id() );
+
+ boost::fibers::fiber f3( boost::fibers::launch::post, fn1);
+ BOOST_CHECK( f2.get_id() != f3.get_id() );
+
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+
+ BOOST_CHECK( boost::fibers::fiber::id() != f1.get_id() );
+ BOOST_CHECK_EQUAL( boost::fibers::fiber::id(), f2.get_id() );
+
+ BOOST_CHECK( ! f2.joinable() );
+
+ f1.join();
+ f3.join();
+}
+
+void test_yield() {
+ int v1 = 0, v2 = 0;
+ BOOST_CHECK_EQUAL( 0, v1);
+ BOOST_CHECK_EQUAL( 0, v2);
+ boost::fibers::fiber f1( boost::fibers::launch::post, fn3, std::ref( v1) );
+ boost::fibers::fiber f2( boost::fibers::launch::post, fn3, std::ref( v2) );
+ f1.join();
+ f2.join();
+ BOOST_CHECK( ! f1.joinable() );
+ BOOST_CHECK( ! f2.joinable() );
+ BOOST_CHECK_EQUAL( 8, v1);
+ BOOST_CHECK_EQUAL( 8, v2);
+}
+
+void test_sleep_for() {
+ typedef std::chrono::system_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_for(ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the fiber system switches the fiber
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+}
+
+void test_sleep_until() {
+ {
+ typedef std::chrono::steady_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_until(t0 + ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+ }
+ {
+ typedef std::chrono::system_clock Clock;
+ typedef Clock::time_point time_point;
+ std::chrono::milliseconds ms(500);
+ time_point t0 = Clock::now();
+ boost::this_fiber::sleep_until(t0 + ms);
+ time_point t1 = Clock::now();
+ std::chrono::nanoseconds ns = (t1 - t0) - ms;
+ std::chrono::nanoseconds err = ms / 10;
+ // This test is spurious as it depends on the time the thread system switches the threads
+ BOOST_CHECK((std::max)(ns.count(), -ns.count()) < (err+std::chrono::milliseconds(1000)).count());
+ }
+}
+
+void do_wait( boost::fibers::barrier* b) {
+ b->wait();
+}
+
+void test_detach() {
+ {
+ boost::fibers::fiber f( boost::fibers::launch::post, (detachable()) );
+ BOOST_CHECK( f.joinable() );
+ f.detach();
+ BOOST_CHECK( ! f.joinable() );
+ boost::this_fiber::sleep_for( std::chrono::milliseconds(250) );
+ BOOST_CHECK( detachable::was_running);
+ BOOST_CHECK_EQUAL( 0, detachable::alive_count);
+ }
+ {
+ boost::fibers::fiber f( boost::fibers::launch::post, (detachable()) );
+ BOOST_CHECK( f.joinable() );
+ boost::this_fiber::yield();
+ f.detach();
+ BOOST_CHECK( ! f.joinable() );
+ boost::this_fiber::sleep_for( std::chrono::milliseconds(250) );
+ BOOST_CHECK( detachable::was_running);
+ BOOST_CHECK_EQUAL( 0, detachable::alive_count);
+ }
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: fiber test suite");
+
+ test->add( BOOST_TEST_CASE( & test_scheduler_dtor) );
+ test->add( BOOST_TEST_CASE( & test_join_fn) );
+ test->add( BOOST_TEST_CASE( & test_join_memfn) );
+ test->add( BOOST_TEST_CASE( & test_join_copyable) );
+ test->add( BOOST_TEST_CASE( & test_join_moveable) );
+ test->add( BOOST_TEST_CASE( & test_join_lambda) );
+ test->add( BOOST_TEST_CASE( & test_join_bind) );
+ test->add( BOOST_TEST_CASE( & test_join_in_fiber) );
+ test->add( BOOST_TEST_CASE( & test_move_fiber) );
+ test->add( BOOST_TEST_CASE( & test_yield) );
+ test->add( BOOST_TEST_CASE( & test_sleep_for) );
+ test->add( BOOST_TEST_CASE( & test_sleep_until) );
+ test->add( BOOST_TEST_CASE( & test_detach) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_fss_dispatch.cpp b/src/boost/libs/fiber/test/test_fss_dispatch.cpp
new file mode 100644
index 00000000..367c6aa1
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_fss_dispatch.cpp
@@ -0,0 +1,237 @@
+// 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)
+
+#include <iostream>
+#include <mutex>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+boost::fibers::mutex check_mutex;
+boost::fibers::mutex fss_mutex;
+int fss_instances = 0;
+int fss_total = 0;
+
+struct fss_value_t {
+ fss_value_t() {
+ std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
+ ++fss_instances;
+ ++fss_total;
+ value = 0;
+ }
+ ~fss_value_t() {
+ std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
+ --fss_instances;
+ }
+ int value;
+};
+
+boost::fibers::fiber_specific_ptr<fss_value_t> fss_value;
+
+void fss_fiber() {
+ fss_value.reset(new fss_value_t());
+ for (int i=0; i<1000; ++i) {
+ int& n = fss_value->value;
+ if (n != i) {
+ std::unique_lock<boost::fibers::mutex> lock(check_mutex);
+ BOOST_CHECK_EQUAL(n, i);
+ }
+ ++n;
+ }
+}
+
+void fss() {
+ fss_instances = 0;
+ fss_total = 0;
+
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, fss_fiber);
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, fss_fiber);
+ boost::fibers::fiber f3( boost::fibers::launch::dispatch, fss_fiber);
+ boost::fibers::fiber f4( boost::fibers::launch::dispatch, fss_fiber);
+ boost::fibers::fiber f5( boost::fibers::launch::dispatch, fss_fiber);
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ std::cout
+ << "fss_instances = " << fss_instances
+ << "; fss_total = " << fss_total
+ << "\n";
+ std::cout.flush();
+
+ BOOST_CHECK_EQUAL(fss_instances, 0);
+ BOOST_CHECK_EQUAL(fss_total, 5);
+}
+
+void test_fss() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fss).join();
+}
+
+bool fss_cleanup_called=false;
+
+struct Dummy {
+};
+
+void fss_custom_cleanup(Dummy* d) {
+ delete d;
+ fss_cleanup_called=true;
+}
+
+boost::fibers::fiber_specific_ptr<Dummy> fss_with_cleanup(fss_custom_cleanup);
+
+void fss_fiber_with_custom_cleanup() {
+ fss_with_cleanup.reset(new Dummy);
+}
+
+void fss_with_custom_cleanup() {
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup);
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(fss_cleanup_called);
+}
+
+void test_fss_with_custom_cleanup() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fss_with_custom_cleanup).join();
+}
+
+Dummy* fss_object=new Dummy;
+
+void fss_fiber_with_custom_cleanup_and_release() {
+ fss_with_cleanup.reset(fss_object);
+ fss_with_cleanup.release();
+}
+
+void do_test_fss_does_no_cleanup_after_release() {
+ fss_cleanup_called=false;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup_and_release);
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(!fss_cleanup_called);
+ if(!fss_cleanup_called) {
+ delete fss_object;
+ }
+}
+
+struct dummy_class_tracks_deletions {
+ static unsigned deletions;
+
+ ~dummy_class_tracks_deletions() {
+ ++deletions;
+ }
+};
+
+unsigned dummy_class_tracks_deletions::deletions=0;
+
+boost::fibers::fiber_specific_ptr<dummy_class_tracks_deletions> fss_with_null_cleanup(NULL);
+
+void fss_fiber_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) {
+ fss_with_null_cleanup.reset(delete_tracker);
+}
+
+void do_test_fss_does_no_cleanup_with_null_cleanup_function() {
+ dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&delete_tracker](){
+ fss_fiber_with_null_cleanup( delete_tracker); });
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(!dummy_class_tracks_deletions::deletions);
+ if(!dummy_class_tracks_deletions::deletions) {
+ delete delete_tracker;
+ }
+}
+
+void test_fss_does_no_cleanup_after_release() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_after_release).join();
+}
+
+void test_fss_does_no_cleanup_with_null_cleanup_function() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_with_null_cleanup_function).join();
+}
+
+
+void fiber_with_local_fss_ptr() {
+ {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+
+ local_fss.reset(new Dummy);
+ }
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+}
+
+void fss_does_not_call_cleanup_after_ptr_destroyed() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fiber_with_local_fss_ptr).join();
+ BOOST_CHECK(!fss_cleanup_called);
+}
+
+void test_fss_does_not_call_cleanup_after_ptr_destroyed() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fss_does_not_call_cleanup_after_ptr_destroyed).join();
+}
+
+
+void fss_cleanup_not_called_for_null_pointer() {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+ local_fss.reset(new Dummy);
+ fss_cleanup_called=false;
+ local_fss.reset(0);
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+ local_fss.reset(new Dummy);
+ BOOST_CHECK(!fss_cleanup_called);
+}
+
+void test_fss_cleanup_not_called_for_null_pointer() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fss_cleanup_not_called_for_null_pointer).join();
+}
+
+
+void fss_at_the_same_adress() {
+ for(int i=0; i<2; i++) {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+ local_fss.reset(new Dummy);
+ fss_cleanup_called=false;
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+ BOOST_CHECK(!fss_cleanup_called);
+ }
+}
+
+void test_fss_at_the_same_adress() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fss_at_the_same_adress).join();
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: fss test suite");
+
+ test->add(BOOST_TEST_CASE(test_fss));
+ test->add(BOOST_TEST_CASE(test_fss_with_custom_cleanup));
+ test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_after_release));
+ test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_with_null_cleanup_function));
+ test->add(BOOST_TEST_CASE(test_fss_does_not_call_cleanup_after_ptr_destroyed));
+ test->add(BOOST_TEST_CASE(test_fss_cleanup_not_called_for_null_pointer));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_fss_post.cpp b/src/boost/libs/fiber/test/test_fss_post.cpp
new file mode 100644
index 00000000..166c4ea1
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_fss_post.cpp
@@ -0,0 +1,237 @@
+// 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)
+
+#include <iostream>
+#include <mutex>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+boost::fibers::mutex check_mutex;
+boost::fibers::mutex fss_mutex;
+int fss_instances = 0;
+int fss_total = 0;
+
+struct fss_value_t {
+ fss_value_t() {
+ std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
+ ++fss_instances;
+ ++fss_total;
+ value = 0;
+ }
+ ~fss_value_t() {
+ std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
+ --fss_instances;
+ }
+ int value;
+};
+
+boost::fibers::fiber_specific_ptr<fss_value_t> fss_value;
+
+void fss_fiber() {
+ fss_value.reset(new fss_value_t());
+ for (int i=0; i<1000; ++i) {
+ int& n = fss_value->value;
+ if (n != i) {
+ std::unique_lock<boost::fibers::mutex> lock(check_mutex);
+ BOOST_CHECK_EQUAL(n, i);
+ }
+ ++n;
+ }
+}
+
+void fss() {
+ fss_instances = 0;
+ fss_total = 0;
+
+ boost::fibers::fiber f1( boost::fibers::launch::post, fss_fiber);
+ boost::fibers::fiber f2( boost::fibers::launch::post, fss_fiber);
+ boost::fibers::fiber f3( boost::fibers::launch::post, fss_fiber);
+ boost::fibers::fiber f4( boost::fibers::launch::post, fss_fiber);
+ boost::fibers::fiber f5( boost::fibers::launch::post, fss_fiber);
+ f1.join();
+ f2.join();
+ f3.join();
+ f4.join();
+ f5.join();
+
+ std::cout
+ << "fss_instances = " << fss_instances
+ << "; fss_total = " << fss_total
+ << "\n";
+ std::cout.flush();
+
+ BOOST_CHECK_EQUAL(fss_instances, 0);
+ BOOST_CHECK_EQUAL(fss_total, 5);
+}
+
+void test_fss() {
+ boost::fibers::fiber( boost::fibers::launch::post, fss).join();
+}
+
+bool fss_cleanup_called=false;
+
+struct Dummy {
+};
+
+void fss_custom_cleanup(Dummy* d) {
+ delete d;
+ fss_cleanup_called=true;
+}
+
+boost::fibers::fiber_specific_ptr<Dummy> fss_with_cleanup(fss_custom_cleanup);
+
+void fss_fiber_with_custom_cleanup() {
+ fss_with_cleanup.reset(new Dummy);
+}
+
+void fss_with_custom_cleanup() {
+ boost::fibers::fiber f( boost::fibers::launch::post, fss_fiber_with_custom_cleanup);
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(fss_cleanup_called);
+}
+
+void test_fss_with_custom_cleanup() {
+ boost::fibers::fiber( boost::fibers::launch::post, fss_with_custom_cleanup).join();
+}
+
+Dummy* fss_object=new Dummy;
+
+void fss_fiber_with_custom_cleanup_and_release() {
+ fss_with_cleanup.reset(fss_object);
+ fss_with_cleanup.release();
+}
+
+void do_test_fss_does_no_cleanup_after_release() {
+ fss_cleanup_called=false;
+ boost::fibers::fiber f( boost::fibers::launch::post, fss_fiber_with_custom_cleanup_and_release);
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(!fss_cleanup_called);
+ if(!fss_cleanup_called) {
+ delete fss_object;
+ }
+}
+
+struct dummy_class_tracks_deletions {
+ static unsigned deletions;
+
+ ~dummy_class_tracks_deletions() {
+ ++deletions;
+ }
+};
+
+unsigned dummy_class_tracks_deletions::deletions=0;
+
+boost::fibers::fiber_specific_ptr<dummy_class_tracks_deletions> fss_with_null_cleanup(NULL);
+
+void fss_fiber_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) {
+ fss_with_null_cleanup.reset(delete_tracker);
+}
+
+void do_test_fss_does_no_cleanup_with_null_cleanup_function() {
+ dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&delete_tracker](){
+ fss_fiber_with_null_cleanup( delete_tracker); });
+ try {
+ f.join();
+ } catch(...) {
+ f.join();
+ throw;
+ }
+
+ BOOST_CHECK(!dummy_class_tracks_deletions::deletions);
+ if(!dummy_class_tracks_deletions::deletions) {
+ delete delete_tracker;
+ }
+}
+
+void test_fss_does_no_cleanup_after_release() {
+ boost::fibers::fiber( boost::fibers::launch::post, do_test_fss_does_no_cleanup_after_release).join();
+}
+
+void test_fss_does_no_cleanup_with_null_cleanup_function() {
+ boost::fibers::fiber( boost::fibers::launch::post, do_test_fss_does_no_cleanup_with_null_cleanup_function).join();
+}
+
+
+void fiber_with_local_fss_ptr() {
+ {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+
+ local_fss.reset(new Dummy);
+ }
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+}
+
+void fss_does_not_call_cleanup_after_ptr_destroyed() {
+ boost::fibers::fiber( boost::fibers::launch::post, fiber_with_local_fss_ptr).join();
+ BOOST_CHECK(!fss_cleanup_called);
+}
+
+void test_fss_does_not_call_cleanup_after_ptr_destroyed() {
+ boost::fibers::fiber( boost::fibers::launch::post, fss_does_not_call_cleanup_after_ptr_destroyed).join();
+}
+
+
+void fss_cleanup_not_called_for_null_pointer() {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+ local_fss.reset(new Dummy);
+ fss_cleanup_called=false;
+ local_fss.reset(0);
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+ local_fss.reset(new Dummy);
+ BOOST_CHECK(!fss_cleanup_called);
+}
+
+void test_fss_cleanup_not_called_for_null_pointer() {
+ boost::fibers::fiber( boost::fibers::launch::post, fss_cleanup_not_called_for_null_pointer).join();
+}
+
+
+void fss_at_the_same_adress() {
+ for(int i=0; i<2; i++) {
+ boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
+ local_fss.reset(new Dummy);
+ fss_cleanup_called=false;
+ BOOST_CHECK(fss_cleanup_called);
+ fss_cleanup_called=false;
+ BOOST_CHECK(!fss_cleanup_called);
+ }
+}
+
+void test_fss_at_the_same_adress() {
+ boost::fibers::fiber( boost::fibers::launch::post, fss_at_the_same_adress).join();
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: fss test suite");
+
+ test->add(BOOST_TEST_CASE(test_fss));
+ test->add(BOOST_TEST_CASE(test_fss_with_custom_cleanup));
+ test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_after_release));
+ test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_with_null_cleanup_function));
+ test->add(BOOST_TEST_CASE(test_fss_does_not_call_cleanup_after_ptr_destroyed));
+ test->add(BOOST_TEST_CASE(test_fss_cleanup_not_called_for_null_pointer));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_future_dispatch.cpp b/src/boost/libs/fiber/test/test_future_dispatch.cpp
new file mode 100644
index 00000000..2990ec41
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_future_dispatch.cpp
@@ -0,0 +1,569 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <chrono>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::milliseconds ms;
+typedef std::chrono::high_resolution_clock Clock;
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+void fn11( boost::fibers::promise< int > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value(3);
+}
+
+void fn12( boost::fibers::promise< int& > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ gi = 5;
+ p.set_value( gi);
+}
+
+void fn13( boost::fibers::promise< void > p) {
+ boost::this_fiber::sleep_for( ms(400) );
+ p.set_value();
+}
+
+// future
+void test_future_create() {
+ // default constructed future is not valid
+ boost::fibers::future< int > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p2;
+ boost::fibers::future< int > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_create_ref() {
+ // default constructed future is not valid
+ boost::fibers::future< int& > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p2;
+ boost::fibers::future< int& > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_create_void() {
+ // default constructed future is not valid
+ boost::fibers::future< void > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p2;
+ boost::fibers::future< void > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< int > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_move_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< int& > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_move_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< void > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_get() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ p1.set_value( 7);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_get_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ A a; a.value = 7;
+ p1.set_value( std::move( a) );
+
+ boost::fibers::future< A > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get().value);
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< A > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_get_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int& > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+
+void test_future_get_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ f1.get();
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< void > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_share() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int j = sf1.get();
+ BOOST_CHECK_EQUAL( i, j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int& > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int & j = sf1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< void > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ sf1.get();
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_wait() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ // wait on future
+ p1.set_value( 7);
+ f1.wait();
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_future_wait_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ // wait on future
+ int i = 7;
+ p1.set_value( i);
+ f1.wait();
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+}
+
+void test_future_wait_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ // wait on future
+ p1.set_value();
+ f1.wait();
+ f1.get();
+ BOOST_CHECK( ! f1.valid() );
+}
+
+void test_future_wait_for() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_for_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_for_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_with_fiber_1() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p1, 7).detach();
+
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ // wait on future
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_future_wait_with_fiber_2() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn2).join();
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: future test suite");
+
+ test->add(BOOST_TEST_CASE(test_future_create));
+ test->add(BOOST_TEST_CASE(test_future_create_ref));
+ test->add(BOOST_TEST_CASE(test_future_create_void));
+ test->add(BOOST_TEST_CASE(test_future_move));
+ test->add(BOOST_TEST_CASE(test_future_move_ref));
+ test->add(BOOST_TEST_CASE(test_future_move_void));
+ test->add(BOOST_TEST_CASE(test_future_get));
+ test->add(BOOST_TEST_CASE(test_future_get_move));
+ test->add(BOOST_TEST_CASE(test_future_get_ref));
+ test->add(BOOST_TEST_CASE(test_future_get_void));
+ test->add(BOOST_TEST_CASE(test_future_share));
+ test->add(BOOST_TEST_CASE(test_future_share_ref));
+ test->add(BOOST_TEST_CASE(test_future_share_void));
+ test->add(BOOST_TEST_CASE(test_future_wait));
+ test->add(BOOST_TEST_CASE(test_future_wait_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_for));
+ test->add(BOOST_TEST_CASE(test_future_wait_for_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_for_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_until));
+ test->add(BOOST_TEST_CASE(test_future_wait_until_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_until_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_with_fiber_1));
+ test->add(BOOST_TEST_CASE(test_future_wait_with_fiber_2));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_future_mt_dispatch.cpp b/src/boost/libs/fiber/test/test_future_mt_dispatch.cpp
new file mode 100644
index 00000000..16585bb0
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_future_mt_dispatch.cpp
@@ -0,0 +1,50 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <thread>
+
+#include <boost/fiber/all.hpp>
+#include <boost/test/unit_test.hpp>
+
+int fn( int i) {
+ return i;
+}
+
+void test_async() {
+ for ( int i = 0; i < 10; ++i) {
+ int n = 3;
+ boost::fibers::packaged_task< int( int) > pt( fn);
+ boost::fibers::future< int > f( pt.get_future() );
+ std::thread t(
+ std::bind(
+ [n](boost::fibers::packaged_task< int( int) > & pt) mutable -> void {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, std::move( pt), n).join();
+ },
+ std::move( pt) ) );
+ int result = f.get();
+ BOOST_CHECK_EQUAL( n, result);
+ t.join();
+ }
+}
+
+void test_dummy() {}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: futures-mt test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add(BOOST_TEST_CASE(test_async));
+#else
+ test->add(BOOST_TEST_CASE(test_dummy));
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_future_mt_post.cpp b/src/boost/libs/fiber/test/test_future_mt_post.cpp
new file mode 100644
index 00000000..ff708a3b
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_future_mt_post.cpp
@@ -0,0 +1,50 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <thread>
+
+#include <boost/fiber/all.hpp>
+#include <boost/test/unit_test.hpp>
+
+int fn( int i) {
+ return i;
+}
+
+void test_async() {
+ for ( int i = 0; i < 10; ++i) {
+ int n = 3;
+ boost::fibers::packaged_task< int( int) > pt( fn);
+ boost::fibers::future< int > f( pt.get_future() );
+ std::thread t(
+ std::bind(
+ [n](boost::fibers::packaged_task< int( int) > & pt) mutable -> void {
+ boost::fibers::fiber( boost::fibers::launch::post, std::move( pt), n).join();
+ },
+ std::move( pt) ) );
+ int result = f.get();
+ BOOST_CHECK_EQUAL( n, result);
+ t.join();
+ }
+}
+
+void test_dummy() {}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: futures-mt test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add(BOOST_TEST_CASE(test_async));
+#else
+ test->add(BOOST_TEST_CASE(test_dummy));
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_future_post.cpp b/src/boost/libs/fiber/test/test_future_post.cpp
new file mode 100644
index 00000000..01deb26f
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_future_post.cpp
@@ -0,0 +1,569 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <chrono>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::milliseconds ms;
+typedef std::chrono::high_resolution_clock Clock;
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+void fn11( boost::fibers::promise< int > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value(3);
+}
+
+void fn12( boost::fibers::promise< int& > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ gi = 5;
+ p.set_value( gi);
+}
+
+void fn13( boost::fibers::promise< void > p) {
+ boost::this_fiber::sleep_for( ms(400) );
+ p.set_value();
+}
+
+// future
+void test_future_create() {
+ // default constructed future is not valid
+ boost::fibers::future< int > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p2;
+ boost::fibers::future< int > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_create_ref() {
+ // default constructed future is not valid
+ boost::fibers::future< int& > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p2;
+ boost::fibers::future< int& > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_create_void() {
+ // default constructed future is not valid
+ boost::fibers::future< void > f1;
+ BOOST_CHECK( ! f1.valid() );
+
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p2;
+ boost::fibers::future< void > f2 = p2.get_future();
+ BOOST_CHECK( f2.valid() );
+}
+
+void test_future_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< int > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_move_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< int& > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_move_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::future< void > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_future_get() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ p1.set_value( 7);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_get_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ A a; a.value = 7;
+ p1.set_value( std::move( a) );
+
+ boost::fibers::future< A > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get().value);
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< A > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_get_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int& > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+
+void test_future_get_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ f1.get();
+ BOOST_CHECK( ! f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< void > p2;
+ f1 = p2.get_future();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_share() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int j = sf1.get();
+ BOOST_CHECK_EQUAL( i, j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int& > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int & j = sf1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< void > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ sf1.get();
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_wait() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ // wait on future
+ p1.set_value( 7);
+ f1.wait();
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_future_wait_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ // wait on future
+ int i = 7;
+ p1.set_value( i);
+ f1.wait();
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+}
+
+void test_future_wait_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ // wait on future
+ p1.set_value();
+ f1.wait();
+ f1.get();
+ BOOST_CHECK( ! f1.valid() );
+}
+
+void test_future_wait_for() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_for_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_for_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_until_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(400) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_future_wait_with_fiber_1() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p1, 7).detach();
+
+ boost::fibers::future< int > f1 = p1.get_future();
+
+ // wait on future
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_future_wait_with_fiber_2() {
+ boost::fibers::fiber( boost::fibers::launch::post, fn2).join();
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: future test suite");
+
+ test->add(BOOST_TEST_CASE(test_future_create));
+ test->add(BOOST_TEST_CASE(test_future_create_ref));
+ test->add(BOOST_TEST_CASE(test_future_create_void));
+ test->add(BOOST_TEST_CASE(test_future_move));
+ test->add(BOOST_TEST_CASE(test_future_move_ref));
+ test->add(BOOST_TEST_CASE(test_future_move_void));
+ test->add(BOOST_TEST_CASE(test_future_get));
+ test->add(BOOST_TEST_CASE(test_future_get_move));
+ test->add(BOOST_TEST_CASE(test_future_get_ref));
+ test->add(BOOST_TEST_CASE(test_future_get_void));
+ test->add(BOOST_TEST_CASE(test_future_share));
+ test->add(BOOST_TEST_CASE(test_future_share_ref));
+ test->add(BOOST_TEST_CASE(test_future_share_void));
+ test->add(BOOST_TEST_CASE(test_future_wait));
+ test->add(BOOST_TEST_CASE(test_future_wait_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_for));
+ test->add(BOOST_TEST_CASE(test_future_wait_for_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_for_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_until));
+ test->add(BOOST_TEST_CASE(test_future_wait_until_ref));
+ test->add(BOOST_TEST_CASE(test_future_wait_until_void));
+ test->add(BOOST_TEST_CASE(test_future_wait_with_fiber_1));
+ test->add(BOOST_TEST_CASE(test_future_wait_with_fiber_2));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_mutex_dispatch.cpp b/src/boost/libs/fiber/test/test_mutex_dispatch.cpp
new file mode 100644
index 00000000..dec8ed4d
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_mutex_dispatch.cpp
@@ -0,0 +1,447 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+int value2 = 0;
+
+template< typename M >
+void fn1( M & mtx) {
+ typedef M mutex_type;
+ typename std::unique_lock< mutex_type > lk( mtx);
+ ++value1;
+ for ( int i = 0; i < 3; ++i)
+ boost::this_fiber::yield();
+}
+
+template< typename M >
+void fn2( M & mtx) {
+ typedef M mutex_type;
+ ++value2;
+ typename std::unique_lock< mutex_type > lk( mtx);
+ ++value2;
+}
+
+void fn3( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
+}
+
+void fn4( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while ( ! m.try_lock() );
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+void fn5( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK( m.try_lock_for(ms(300)+ms(2000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn6( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn7( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5ms
+}
+
+void fn8( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ ns r = ns(5000000)+ms(2000); // within 6ms
+ BOOST_CHECK(d < r); // within 6ms
+}
+
+void fn9( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.lock();
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(2500)+ms(2000)); // within 2.5 ms
+}
+
+void fn10( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock()) ;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(50000)+ms(2000)); // within 50 ms
+}
+
+void fn11( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(300)+ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn12( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(5000)+ms(2000)); // within 5 ms
+}
+
+void fn13( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn14( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn15( boost::fibers::recursive_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.lock();
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
+}
+
+void fn16( boost::fibers::recursive_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock());
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+void fn17( boost::fibers::mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(2500)+ms(2000)); // within 2.5 ms
+}
+
+void fn18( boost::fibers::mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock()) ;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+template< typename M >
+struct test_lock {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ mutex_type mtx;
+
+ // Test the lock's constructors.
+ {
+ lock_type lk(mtx, std::defer_lock);
+ BOOST_CHECK(!lk);
+ }
+ lock_type lk(mtx);
+ BOOST_CHECK(lk ? true : false);
+
+ // Test the lock and unlock methods.
+ lk.unlock();
+ BOOST_CHECK(!lk);
+ lk.lock();
+ BOOST_CHECK(lk ? true : false);
+ }
+};
+
+template< typename M >
+struct test_exclusive {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ value1 = 0;
+ value2 = 0;
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ mutex_type mtx;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, & fn1< mutex_type >, std::ref( mtx) );
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, & fn2< mutex_type >, std::ref( mtx) );
+ BOOST_ASSERT( f1.joinable() );
+ BOOST_ASSERT( f2.joinable() );
+
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ }
+};
+
+template< typename M >
+struct test_recursive_lock {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ mutex_type mx;
+ lock_type lock1(mx);
+ lock_type lock2(mx);
+ }
+};
+
+void do_test_mutex() {
+ test_lock< boost::fibers::mutex >()();
+ test_exclusive< boost::fibers::mutex >()();
+
+ {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn17, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn18, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+}
+
+void test_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_mutex).join();
+}
+
+void do_test_recursive_mutex() {
+ test_lock< boost::fibers::recursive_mutex >()();
+ test_exclusive< boost::fibers::recursive_mutex >()();
+ test_recursive_lock< boost::fibers::recursive_mutex >()();
+
+ {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn15, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn16, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+}
+
+void test_recursive_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_recursive_mutex).join();
+}
+
+void do_test_timed_mutex() {
+ test_lock< boost::fibers::timed_mutex >()();
+ test_exclusive< boost::fibers::timed_mutex >()();
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn6, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn7, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn8, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) + ms(1000) );
+ timed_mtx.unlock();
+ f.join();
+ }
+}
+
+void test_timed_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_timed_mutex).join();
+}
+
+void do_test_recursive_timed_mutex() {
+ test_lock< boost::fibers::recursive_timed_mutex >()();
+ test_exclusive< boost::fibers::recursive_timed_mutex >()();
+ test_recursive_lock< boost::fibers::recursive_timed_mutex >()();
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn9, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn10, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn11, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn12, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(400) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn13, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn14, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) );
+ timed_mtx.unlock();
+ f.join();
+ }
+}
+
+void test_recursive_timed_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_recursive_timed_mutex).join();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: mutex test suite");
+
+ test->add( BOOST_TEST_CASE( & test_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_mutex) );
+ test->add( BOOST_TEST_CASE( & test_timed_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_mutex_mt_dispatch.cpp b/src/boost/libs/fiber/test/test_mutex_mt_dispatch.cpp
new file mode 100644
index 00000000..2087d17c
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_mutex_mt_dispatch.cpp
@@ -0,0 +1,139 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/chrono.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/thread/thread.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef boost::chrono::nanoseconds ns;
+typedef boost::chrono::milliseconds ms;
+
+int value1 = 0;
+int value2 = 0;
+
+template< typename Mtx >
+void g( boost::barrier & b, Mtx & m) {
+ b.wait();
+ m.lock();
+ value1 = 3;
+ m.unlock();
+}
+
+template< typename Mtx >
+void f( boost::barrier & b, Mtx & m) {
+ b.wait();
+ m.lock();
+ value2 = 7;
+ m.unlock();
+}
+
+template< typename Mtx >
+void fn1( boost::barrier & b, Mtx & m) {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, g< Mtx >, std::ref( b), std::ref( m) ).join();
+}
+
+template< typename Mtx >
+void fn2( boost::barrier & b, Mtx & m) {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, f< Mtx >, std::ref( b), std::ref( m) ).join();
+}
+
+void test_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_recursive_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::recursive_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::recursive_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_timed_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::timed_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::timed_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::timed_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_recursive_timed_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::recursive_timed_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::recursive_timed_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::recursive_timed_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_dummy() {
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: multithreaded mutex test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add( BOOST_TEST_CASE( & test_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_mutex) );
+ test->add( BOOST_TEST_CASE( & test_timed_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );
+#else
+ test->add( BOOST_TEST_CASE( & test_dummy) );
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_mutex_mt_post.cpp b/src/boost/libs/fiber/test/test_mutex_mt_post.cpp
new file mode 100644
index 00000000..758acf9d
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_mutex_mt_post.cpp
@@ -0,0 +1,139 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/chrono.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/thread/thread.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef boost::chrono::nanoseconds ns;
+typedef boost::chrono::milliseconds ms;
+
+int value1 = 0;
+int value2 = 0;
+
+template< typename Mtx >
+void g( boost::barrier & b, Mtx & m) {
+ b.wait();
+ m.lock();
+ value1 = 3;
+ m.unlock();
+}
+
+template< typename Mtx >
+void f( boost::barrier & b, Mtx & m) {
+ b.wait();
+ m.lock();
+ value2 = 7;
+ m.unlock();
+}
+
+template< typename Mtx >
+void fn1( boost::barrier & b, Mtx & m) {
+ boost::fibers::fiber( boost::fibers::launch::post, g< Mtx >, std::ref( b), std::ref( m) ).join();
+}
+
+template< typename Mtx >
+void fn2( boost::barrier & b, Mtx & m) {
+ boost::fibers::fiber( boost::fibers::launch::post, f< Mtx >, std::ref( b), std::ref( m) ).join();
+}
+
+void test_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_recursive_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::recursive_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::recursive_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_timed_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::timed_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::timed_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::timed_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_recursive_timed_mutex() {
+ for ( int i = 0; i < 10; ++i) {
+ boost::fibers::recursive_timed_mutex mtx;
+ mtx.lock();
+ boost::barrier b( 3);
+ boost::thread t1( fn1< boost::fibers::recursive_timed_mutex >, std::ref( b), std::ref( mtx) );
+ boost::thread t2( fn2< boost::fibers::recursive_timed_mutex >, std::ref( b), std::ref( mtx) );
+ b.wait();
+ boost::this_thread::sleep_for( ms( 250) );
+ mtx.unlock();
+ t1.join();
+ t2.join();
+ BOOST_CHECK( 3 == value1);
+ BOOST_CHECK( 7 == value2);
+ }
+}
+
+void test_dummy() {
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: multithreaded mutex test suite");
+
+#if ! defined(BOOST_FIBERS_NO_ATOMICS)
+ test->add( BOOST_TEST_CASE( & test_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_mutex) );
+ test->add( BOOST_TEST_CASE( & test_timed_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );
+#else
+ test->add( BOOST_TEST_CASE( & test_dummy) );
+#endif
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_mutex_post.cpp b/src/boost/libs/fiber/test/test_mutex_post.cpp
new file mode 100644
index 00000000..f88a571f
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_mutex_post.cpp
@@ -0,0 +1,447 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 test is based on the tests of Boost.Thread
+
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::nanoseconds ns;
+typedef std::chrono::milliseconds ms;
+
+int value1 = 0;
+int value2 = 0;
+
+template< typename M >
+void fn1( M & mtx) {
+ typedef M mutex_type;
+ typename std::unique_lock< mutex_type > lk( mtx);
+ ++value1;
+ for ( int i = 0; i < 3; ++i)
+ boost::this_fiber::yield();
+}
+
+template< typename M >
+void fn2( M & mtx) {
+ typedef M mutex_type;
+ ++value2;
+ typename std::unique_lock< mutex_type > lk( mtx);
+ ++value2;
+}
+
+void fn3( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
+}
+
+void fn4( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while ( ! m.try_lock() );
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+void fn5( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK( m.try_lock_for(ms(300)+ms(2000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn6( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn7( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5ms
+}
+
+void fn8( boost::fibers::timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ ns r = ns(5000000)+ms(2000); // within 6ms
+ BOOST_CHECK(d < r); // within 6ms
+}
+
+void fn9( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.lock();
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(2500)+ms(2000)); // within 2.5 ms
+}
+
+void fn10( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock()) ;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+void fn11( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(300)+ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn12( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_for(ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ms(5000)+ms(2000)); // within 5 ms
+}
+
+void fn13( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(300) + ms(1000)) == true);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn14( boost::fibers::recursive_timed_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock_until(std::chrono::steady_clock::now() + ms(250)) == false);
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(5000000)+ms(2000)); // within 5 ms
+}
+
+void fn15( boost::fibers::recursive_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.lock();
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
+}
+
+void fn16( boost::fibers::recursive_mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock());
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ BOOST_CHECK(m.try_lock());
+ m.unlock();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+void fn17( boost::fibers::mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ m.lock();
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(2500000)+ms(2000)); // within 2.5 ms
+}
+
+void fn18( boost::fibers::mutex & m) {
+ std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
+ while (!m.try_lock()) ;
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+ m.unlock();
+ ns d = t1 - t0 - ms(250);
+ BOOST_CHECK(d < ns(50000000)+ms(2000)); // within 50 ms
+}
+
+template< typename M >
+struct test_lock {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ mutex_type mtx;
+
+ // Test the lock's constructors.
+ {
+ lock_type lk(mtx, std::defer_lock);
+ BOOST_CHECK(!lk);
+ }
+ lock_type lk(mtx);
+ BOOST_CHECK(lk ? true : false);
+
+ // Test the lock and unlock methods.
+ lk.unlock();
+ BOOST_CHECK(!lk);
+ lk.lock();
+ BOOST_CHECK(lk ? true : false);
+ }
+};
+
+template< typename M >
+struct test_exclusive {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ value1 = 0;
+ value2 = 0;
+ BOOST_CHECK_EQUAL( 0, value1);
+ BOOST_CHECK_EQUAL( 0, value2);
+
+ mutex_type mtx;
+ boost::fibers::fiber f1( boost::fibers::launch::post, & fn1< mutex_type >, std::ref( mtx) );
+ boost::fibers::fiber f2( boost::fibers::launch::post, & fn2< mutex_type >, std::ref( mtx) );
+ BOOST_ASSERT( f1.joinable() );
+ BOOST_ASSERT( f2.joinable() );
+
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, value1);
+ BOOST_CHECK_EQUAL( 2, value2);
+ }
+};
+
+template< typename M >
+struct test_recursive_lock {
+ typedef M mutex_type;
+ typedef typename std::unique_lock< M > lock_type;
+
+ void operator()() {
+ mutex_type mx;
+ lock_type lock1(mx);
+ lock_type lock2(mx);
+ }
+};
+
+void do_test_mutex() {
+ test_lock< boost::fibers::mutex >()();
+ test_exclusive< boost::fibers::mutex >()();
+
+ {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn17, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn18, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+}
+
+void test_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_mutex).join();
+}
+
+void do_test_recursive_mutex() {
+ test_lock< boost::fibers::recursive_mutex >()();
+ test_exclusive< boost::fibers::recursive_mutex >()();
+ test_recursive_lock< boost::fibers::recursive_mutex >()();
+
+ {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn15, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_mutex mtx;
+ mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn16, std::ref( mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ mtx.unlock();
+ f.join();
+ }
+}
+
+void test_recursive_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::post, do_test_recursive_mutex).join();
+}
+
+void do_test_timed_mutex() {
+ test_lock< boost::fibers::timed_mutex >()();
+ test_exclusive< boost::fibers::timed_mutex >()();
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn3, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn4, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn5, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn6, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn7, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn8, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) + ms(1000) );
+ timed_mtx.unlock();
+ f.join();
+ }
+}
+
+void test_timed_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_timed_mutex).join();
+}
+
+void do_test_recursive_timed_mutex() {
+ test_lock< boost::fibers::recursive_timed_mutex >()();
+ test_exclusive< boost::fibers::recursive_timed_mutex >()();
+ test_recursive_lock< boost::fibers::recursive_timed_mutex >()();
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn9, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn10, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn11, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn12, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(400) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn13, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(250) );
+ timed_mtx.unlock();
+ f.join();
+ }
+
+ {
+ boost::fibers::recursive_timed_mutex timed_mtx;
+ timed_mtx.lock();
+ boost::fibers::fiber f( boost::fibers::launch::post, & fn14, std::ref( timed_mtx) );
+ boost::this_fiber::sleep_for( ms(300) );
+ timed_mtx.unlock();
+ f.join();
+ }
+}
+
+void test_recursive_timed_mutex() {
+ boost::fibers::fiber( boost::fibers::launch::post, & do_test_recursive_timed_mutex).join();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: mutex test suite");
+
+ test->add( BOOST_TEST_CASE( & test_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_mutex) );
+ test->add( BOOST_TEST_CASE( & test_timed_mutex) );
+ test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_packaged_task_dispatch.cpp b/src/boost/libs/fiber/test/test_packaged_task_dispatch.cpp
new file mode 100644
index 00000000..36475583
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_packaged_task_dispatch.cpp
@@ -0,0 +1,679 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+struct B {
+ bool bset{ false };
+
+ B() = default;
+
+ B( bool set) :
+ bset{ set } {
+ gi = 3;
+ }
+
+ ~B() {
+ if ( bset) {
+ gi = -1;
+ }
+ }
+
+ B( B && other) :
+ bset{ other.bset } {
+ other.bset = false;
+ }
+
+ B & operator=( B && other) {
+ if ( this == & other) return * this;
+ bset = other.bset;
+ other.bset = false;
+ return * this;
+ }
+
+ B( B const&) = delete;
+ B & operator=( B const&) = delete;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+B fn11( bool set) {
+ B b( set);
+ return b;
+}
+
+// packaged_task
+void test_packaged_task_create() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< int() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< int() > t2( fn3);
+ BOOST_CHECK( t2.valid() );
+}
+
+// packaged_task
+void test_packaged_task_create_move() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< A() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< A() > t2( fn9);
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_create_void() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< void() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< void() > t2( fn4);
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_move() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< int() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_move_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< A() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_move_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< void() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_swap() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< int() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_swap_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< A() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_swap_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< void() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_reset() {
+ {
+ boost::fibers::packaged_task< int() > p( fn3);
+ boost::fibers::future< int > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ BOOST_CHECK( 3 == f.get() );
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ BOOST_CHECK( 3 == f.get() );
+ }
+ {
+ boost::fibers::packaged_task< int() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_reset_destruction() {
+ gi = 0;
+ boost::fibers::packaged_task< B( bool) > p( fn11);
+ BOOST_CHECK( p.valid() );
+
+ BOOST_CHECK( 0 == gi);
+ p( true);
+ BOOST_CHECK( 3 == gi);
+
+ // reset
+ p.reset();
+ BOOST_CHECK( -1 == gi);
+ p( false);
+ BOOST_CHECK( 3 == gi);
+
+ // reset
+ p.reset();
+ BOOST_CHECK( 3 == gi);
+}
+
+void test_packaged_task_reset_move() {
+ {
+ boost::fibers::packaged_task< A() > p( fn9);
+ boost::fibers::future< A > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ BOOST_CHECK( 3 == f.get().value);
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ BOOST_CHECK( 3 == f.get().value);
+ }
+ {
+ boost::fibers::packaged_task< A() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_reset_void() {
+ {
+ boost::fibers::packaged_task< void() > p( fn4);
+ boost::fibers::future< void > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ f.get();
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ f.get();
+ }
+ {
+ boost::fibers::packaged_task< void() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_get_future() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< int() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_get_future_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< A() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_get_future_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< void() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ BOOST_CHECK( 3 == f1.get() );
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec_move() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ BOOST_CHECK( 3 == f1.get().value);
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec_param() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int( int) > t1( fn8);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1( 3);
+ BOOST_CHECK( 3 == f1.get() );
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1( 7);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ //TODO: packaged_task returns a moveable-only as return type
+}
+
+void test_packaged_task_exec_ref() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int&() > t1( fn7);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int& > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ int & i = f1.get();
+ BOOST_CHECK( &gi == &i);
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ //TODO: packaged_task returns a moveable-only as return type
+}
+
+void test_packaged_task_exec_void() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ t1();
+ f1.get();
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int() > t1( fn5);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< int() > t2( fn5);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< int > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try
+ { std::rethrow_exception( f2.get_exception_ptr() ); }
+ catch ( my_exception const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception_move() {
+ // promise takes a moveable as return type
+ boost::fibers::packaged_task< A() > t1( fn10);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< A() > t2( fn10);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< A > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try
+ { std::rethrow_exception( f2.get_exception_ptr() ); }
+ catch ( my_exception const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception_void() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< void() > t1( fn6);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< void() > t2( fn6);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< void > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try {
+ std::rethrow_exception( f2.get_exception_ptr() );
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: packaged_task test suite");
+
+ test->add(BOOST_TEST_CASE(test_packaged_task_create));
+ test->add(BOOST_TEST_CASE(test_packaged_task_create_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_create_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_destruction));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_param));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_ref));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception_void));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_packaged_task_post.cpp b/src/boost/libs/fiber/test/test_packaged_task_post.cpp
new file mode 100644
index 00000000..53c42d85
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_packaged_task_post.cpp
@@ -0,0 +1,679 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+struct B {
+ bool bset{ false };
+
+ B() = default;
+
+ B( bool set) :
+ bset{ set } {
+ gi = 3;
+ }
+
+ ~B() {
+ if ( bset) {
+ gi = -1;
+ }
+ }
+
+ B( B && other) :
+ bset{ other.bset } {
+ other.bset = false;
+ }
+
+ B & operator=( B && other) {
+ if ( this == & other) return * this;
+ bset = other.bset;
+ other.bset = false;
+ return * this;
+ }
+
+ B( B const&) = delete;
+ B & operator=( B const&) = delete;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+B fn11( bool set) {
+ B b( set);
+ return b;
+}
+
+// packaged_task
+void test_packaged_task_create() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< int() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< int() > t2( fn3);
+ BOOST_CHECK( t2.valid() );
+}
+
+// packaged_task
+void test_packaged_task_create_move() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< A() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< A() > t2( fn9);
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_create_void() {
+ // default constructed packaged_task is not valid
+ boost::fibers::packaged_task< void() > t1;
+ BOOST_CHECK( ! t1.valid() );
+
+ // packaged_task from function
+ boost::fibers::packaged_task< void() > t2( fn4);
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_move() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< int() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_move_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< A() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_move_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ // move construction
+ boost::fibers::packaged_task< void() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // move assignment
+ t1 = std::move( t2);
+ BOOST_CHECK( t1.valid() );
+ BOOST_CHECK( ! t2.valid() );
+}
+
+void test_packaged_task_swap() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< int() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_swap_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< A() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_swap_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ boost::fibers::packaged_task< void() > t2;
+ BOOST_CHECK( ! t2.valid() );
+
+ // swap
+ t1.swap( t2);
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+}
+
+void test_packaged_task_reset() {
+ {
+ boost::fibers::packaged_task< int() > p( fn3);
+ boost::fibers::future< int > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ BOOST_CHECK( 3 == f.get() );
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ BOOST_CHECK( 3 == f.get() );
+ }
+ {
+ boost::fibers::packaged_task< int() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_reset_destruction() {
+ gi = 0;
+ boost::fibers::packaged_task< B( bool) > p( fn11);
+ BOOST_CHECK( p.valid() );
+
+ BOOST_CHECK( 0 == gi);
+ p( true);
+ BOOST_CHECK( 3 == gi);
+
+ // reset
+ p.reset();
+ BOOST_CHECK( -1 == gi);
+ p( false);
+ BOOST_CHECK( 3 == gi);
+
+ // reset
+ p.reset();
+ BOOST_CHECK( 3 == gi);
+}
+
+void test_packaged_task_reset_move() {
+ {
+ boost::fibers::packaged_task< A() > p( fn9);
+ boost::fibers::future< A > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ BOOST_CHECK( 3 == f.get().value);
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ BOOST_CHECK( 3 == f.get().value);
+ }
+ {
+ boost::fibers::packaged_task< A() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_reset_void() {
+ {
+ boost::fibers::packaged_task< void() > p( fn4);
+ boost::fibers::future< void > f( p.get_future() );
+ BOOST_CHECK( p.valid() );
+
+ p();
+ f.get();
+
+ // reset
+ p.reset();
+ p();
+ f = p.get_future();
+ f.get();
+ }
+ {
+ boost::fibers::packaged_task< void() > p;
+
+ bool thrown = false;
+ try {
+ p.reset();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+ }
+}
+
+void test_packaged_task_get_future() {
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< int() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_get_future_move() {
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< A() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_get_future_void() {
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+
+ // retrieve future
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::packaged_task< void() > t2( std::move( t1) );
+ BOOST_CHECK( ! t1.valid() );
+ BOOST_CHECK( t2.valid() );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = t1.get_future();
+ } catch ( boost::fibers::packaged_task_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int() > t1( fn3);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ BOOST_CHECK( 3 == f1.get() );
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec_move() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< A() > t1( fn9);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ BOOST_CHECK( 3 == f1.get().value);
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exec_param() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int( int) > t1( fn8);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1( 3);
+ BOOST_CHECK( 3 == f1.get() );
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1( 7);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ //TODO: packaged_task returns a moveable-only as return type
+}
+
+void test_packaged_task_exec_ref() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int&() > t1( fn7);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int& > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ int & i = f1.get();
+ BOOST_CHECK( &gi == &i);
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ //TODO: packaged_task returns a moveable-only as return type
+}
+
+void test_packaged_task_exec_void() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< void() > t1( fn4);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ t1();
+ f1.get();
+
+ // exec a second time
+ bool thrown = false;
+ try {
+ t1();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< int() > t1( fn5);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< int > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< int() > t2( fn5);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< int > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try
+ { std::rethrow_exception( f2.get_exception_ptr() ); }
+ catch ( my_exception const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception_move() {
+ // promise takes a moveable as return type
+ boost::fibers::packaged_task< A() > t1( fn10);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< A > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // exec
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< A() > t2( fn10);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< A > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try
+ { std::rethrow_exception( f2.get_exception_ptr() ); }
+ catch ( my_exception const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_packaged_task_exception_void() {
+ // promise takes a copyable as return type
+ boost::fibers::packaged_task< void() > t1( fn6);
+ BOOST_CHECK( t1.valid() );
+ boost::fibers::future< void > f1 = t1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ t1();
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ boost::fibers::packaged_task< void() > t2( fn6);
+ BOOST_CHECK( t2.valid() );
+ boost::fibers::future< void > f2 = t2.get_future();
+ BOOST_CHECK( f2.valid() );
+
+ // exec
+ t2();
+ BOOST_CHECK( f2.get_exception_ptr() );
+ thrown = false;
+ try {
+ std::rethrow_exception( f2.get_exception_ptr() );
+ } catch ( my_exception const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: packaged_task test suite");
+
+ test->add(BOOST_TEST_CASE(test_packaged_task_create));
+ test->add(BOOST_TEST_CASE(test_packaged_task_create_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_create_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_move_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_swap_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_destruction));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_reset_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_get_future_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_param));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_ref));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exec_void));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception_move));
+ test->add(BOOST_TEST_CASE(test_packaged_task_exception_void));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_promise_dispatch.cpp b/src/boost/libs/fiber/test/test_promise_dispatch.cpp
new file mode 100644
index 00000000..d3f90f22
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_promise_dispatch.cpp
@@ -0,0 +1,445 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value{ 0 };
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+// promise
+void test_promise_create() {
+ // use std::allocator<> as default
+ boost::fibers::promise< int > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< int > > alloc;
+ boost::fibers::promise< int > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_create_ref() {
+ // use std::allocator<> as default
+ boost::fibers::promise< int& > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< int& > > alloc;
+ boost::fibers::promise< int& > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_create_void() {
+ // use std::allocator<> as default
+ boost::fibers::promise< void > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< void > > alloc;
+ boost::fibers::promise< void > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_move() {
+ boost::fibers::promise< int > p1;
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_move_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_move_void() {
+ boost::fibers::promise< void > p1;
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_swap() {
+ boost::fibers::promise< int > p1;
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_swap_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_swap_void() {
+ boost::fibers::promise< void > p1;
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_get_future() {
+ boost::fibers::promise< int > p1;
+
+ // retrieve future
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_get_future_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // retrieve future
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_get_future_void() {
+ boost::fibers::promise< void > p1;
+
+ // retrieve future
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // copy value
+ p1.set_value( 7);
+ BOOST_CHECK( 7 == f1.get() );
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value( 11);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_move() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< A > p1;
+ boost::fibers::future< A > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move value
+ A a1; a1.value = 7;
+ p1.set_value( std::move( a1) );
+ A a2 = f1.get();
+ BOOST_CHECK( 7 == a2.value);
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ A a;
+ p1.set_value( std::move( a) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_ref() {
+ // promise takes a reference as return type
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // copy value
+ int i = 7;
+ p1.set_value( i);
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value( i);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_void() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ p1.set_value();
+ f1.get();
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ try
+ { p1.set_value( 11); }
+ catch ( boost::fibers::promise_already_satisfied const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception_ref() {
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ int i = 11;
+ try {
+ p1.set_value( i);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception_void() {
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ try {
+ p1.set_value();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: promise test suite");
+
+ test->add(BOOST_TEST_CASE(test_promise_create));
+ test->add(BOOST_TEST_CASE(test_promise_create_ref));
+ test->add(BOOST_TEST_CASE(test_promise_create_void));
+ test->add(BOOST_TEST_CASE(test_promise_move));
+ test->add(BOOST_TEST_CASE(test_promise_move_ref));
+ test->add(BOOST_TEST_CASE(test_promise_move_void));
+ test->add(BOOST_TEST_CASE(test_promise_swap));
+ test->add(BOOST_TEST_CASE(test_promise_swap_ref));
+ test->add(BOOST_TEST_CASE(test_promise_swap_void));
+ test->add(BOOST_TEST_CASE(test_promise_get_future));
+ test->add(BOOST_TEST_CASE(test_promise_get_future_ref));
+ test->add(BOOST_TEST_CASE(test_promise_get_future_void));
+ test->add(BOOST_TEST_CASE(test_promise_set_value));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_move));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_ref));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_void));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception_ref));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception_void));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_promise_post.cpp b/src/boost/libs/fiber/test/test_promise_post.cpp
new file mode 100644
index 00000000..f14936f7
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_promise_post.cpp
@@ -0,0 +1,445 @@
+// (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)
+
+#include <utility>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value{ 0 };
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::future< int > f( p.get_future() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+// promise
+void test_promise_create() {
+ // use std::allocator<> as default
+ boost::fibers::promise< int > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< int > > alloc;
+ boost::fibers::promise< int > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_create_ref() {
+ // use std::allocator<> as default
+ boost::fibers::promise< int& > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< int& > > alloc;
+ boost::fibers::promise< int& > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_create_void() {
+ // use std::allocator<> as default
+ boost::fibers::promise< void > p1;
+
+ // use std::allocator<> as user defined
+ std::allocator< boost::fibers::promise< void > > alloc;
+ boost::fibers::promise< void > p2( std::allocator_arg, alloc);
+}
+
+void test_promise_move() {
+ boost::fibers::promise< int > p1;
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_move_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_move_void() {
+ boost::fibers::promise< void > p1;
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // move assigment
+ p1 = std::move( p2);
+}
+
+void test_promise_swap() {
+ boost::fibers::promise< int > p1;
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_swap_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_swap_void() {
+ boost::fibers::promise< void > p1;
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // swap
+ p1.swap( p2);
+}
+
+void test_promise_get_future() {
+ boost::fibers::promise< int > p1;
+
+ // retrieve future
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< int > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_get_future_ref() {
+ boost::fibers::promise< int& > p1;
+
+ // retrieve future
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< int& > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_get_future_void() {
+ boost::fibers::promise< void > p1;
+
+ // retrieve future
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // retrieve future a second time
+ bool thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::future_already_retrieved const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // move construction
+ boost::fibers::promise< void > p2( std::move( p1) );
+
+ // retrieve future from uninitialized
+ thrown = false;
+ try {
+ f1 = p1.get_future();
+ } catch ( boost::fibers::promise_uninitialized const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // copy value
+ p1.set_value( 7);
+ BOOST_CHECK( 7 == f1.get() );
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value( 11);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_move() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< A > p1;
+ boost::fibers::future< A > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // move value
+ A a1; a1.value = 7;
+ p1.set_value( std::move( a1) );
+ A a2 = f1.get();
+ BOOST_CHECK( 7 == a2.value);
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ A a;
+ p1.set_value( std::move( a) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_ref() {
+ // promise takes a reference as return type
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // copy value
+ int i = 7;
+ p1.set_value( i);
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value( i);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_value_void() {
+ // promise takes a copyable as return type
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // set void
+ p1.set_value();
+ f1.get();
+
+ // set value a second time
+ bool thrown = false;
+ try {
+ p1.set_value();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ try
+ { p1.set_value( 11); }
+ catch ( boost::fibers::promise_already_satisfied const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception_ref() {
+ boost::fibers::promise< int& > p1;
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ int i = 11;
+ try {
+ p1.set_value( i);
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_promise_set_exception_void() {
+ boost::fibers::promise< void > p1;
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+
+ // set exception a second time
+ bool thrown = false;
+ try {
+ p1.set_exception( std::make_exception_ptr( my_exception() ) );
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+
+ // set value
+ thrown = false;
+ try {
+ p1.set_value();
+ } catch ( boost::fibers::promise_already_satisfied const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: promise test suite");
+
+ test->add(BOOST_TEST_CASE(test_promise_create));
+ test->add(BOOST_TEST_CASE(test_promise_create_ref));
+ test->add(BOOST_TEST_CASE(test_promise_create_void));
+ test->add(BOOST_TEST_CASE(test_promise_move));
+ test->add(BOOST_TEST_CASE(test_promise_move_ref));
+ test->add(BOOST_TEST_CASE(test_promise_move_void));
+ test->add(BOOST_TEST_CASE(test_promise_swap));
+ test->add(BOOST_TEST_CASE(test_promise_swap_ref));
+ test->add(BOOST_TEST_CASE(test_promise_swap_void));
+ test->add(BOOST_TEST_CASE(test_promise_get_future));
+ test->add(BOOST_TEST_CASE(test_promise_get_future_ref));
+ test->add(BOOST_TEST_CASE(test_promise_get_future_void));
+ test->add(BOOST_TEST_CASE(test_promise_set_value));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_move));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_ref));
+ test->add(BOOST_TEST_CASE(test_promise_set_value_void));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception_ref));
+ test->add(BOOST_TEST_CASE(test_promise_set_exception_void));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_shared_future_dispatch.cpp b/src/boost/libs/fiber/test/test_shared_future_dispatch.cpp
new file mode 100644
index 00000000..2dd327ff
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_shared_future_dispatch.cpp
@@ -0,0 +1,608 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <chrono>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::milliseconds ms;
+typedef std::chrono::high_resolution_clock Clock;
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::shared_future< int > f( p.get_future().share() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+void fn11( boost::fibers::promise< int > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value(3);
+}
+
+void fn12( boost::fibers::promise< int& > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ gi = 5;
+ p.set_value( gi);
+}
+
+void fn13( boost::fibers::promise< void > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value();
+}
+
+// shared_future
+void test_shared_future_create() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< int > f1;
+ boost::fibers::shared_future< int > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< int > p;
+ boost::fibers::shared_future< int > f1 = p.get_future();
+ boost::fibers::shared_future< int > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_create_ref() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< int& > f1;
+ boost::fibers::shared_future< int& > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< int& > p;
+ boost::fibers::shared_future< int& > f1 = p.get_future();
+ boost::fibers::shared_future< int& > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_create_void() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< void > f1;
+ boost::fibers::shared_future< void > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< void > p;
+ boost::fibers::shared_future< void > f1 = p.get_future();
+ boost::fibers::shared_future< void > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_get() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ p1.set_value( 7);
+
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get() );
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_shared_future_get_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ A a; a.value = 7;
+ p1.set_value( std::move( a) );
+
+ boost::fibers::shared_future< A > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get().value);
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< A > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_shared_future_get_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int& > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+
+void test_shared_future_get_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ f1.get();
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< void > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_share() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int j = sf1.get();
+ BOOST_CHECK_EQUAL( i, j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int& > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int & j = sf1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< void > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ sf1.get();
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_shared_future_wait() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ // wait on future
+ p1.set_value( 7);
+ f1.wait();
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_shared_future_wait_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ // wait on future
+ int i = 7;
+ p1.set_value( i);
+ f1.wait();
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+}
+
+void test_shared_future_wait_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ // wait on future
+ p1.set_value();
+ f1.wait();
+ f1.get();
+ BOOST_CHECK( f1.valid() );
+}
+
+void test_shared_future_wait_for() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_for_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_for_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_with_fiber_1() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p1, 7).detach();
+
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ // wait on future
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_shared_future_wait_with_fiber_2() {
+ boost::fibers::fiber( boost::fibers::launch::dispatch, fn2).join();
+}
+
+void test_shared_future_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< int > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ boost::fibers::shared_future< A > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< A > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< int& > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< void > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
+
+ test->add(BOOST_TEST_CASE(test_shared_future_create));
+ test->add(BOOST_TEST_CASE(test_shared_future_create_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_create_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_get));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_shared_future_post.cpp b/src/boost/libs/fiber/test/test_shared_future_post.cpp
new file mode 100644
index 00000000..2e429f31
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_shared_future_post.cpp
@@ -0,0 +1,608 @@
+// (C) Copyright 2008-10 Anthony Williams
+// 2015 Oliver Kowalke
+//
+// Distributed under the 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 <chrono>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+typedef std::chrono::milliseconds ms;
+typedef std::chrono::high_resolution_clock Clock;
+
+int gi = 7;
+
+struct my_exception : public std::runtime_error {
+ my_exception() :
+ std::runtime_error("my_exception") {
+ }
+};
+
+struct A {
+ A() = default;
+
+ A( A const&) = delete;
+ A( A &&) = default;
+
+ A & operator=( A const&) = delete;
+ A & operator=( A &&) = default;
+
+ int value;
+};
+
+void fn1( boost::fibers::promise< int > * p, int i) {
+ boost::this_fiber::yield();
+ p->set_value( i);
+}
+
+void fn2() {
+ boost::fibers::promise< int > p;
+ boost::fibers::shared_future< int > f( p.get_future().share() );
+ boost::this_fiber::yield();
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
+ boost::this_fiber::yield();
+ BOOST_CHECK( 7 == f.get() );
+}
+
+int fn3() {
+ return 3;
+}
+
+void fn4() {
+}
+
+int fn5() {
+ boost::throw_exception( my_exception() );
+ return 3;
+}
+
+void fn6() {
+ boost::throw_exception( my_exception() );
+}
+
+int & fn7() {
+ return gi;
+}
+
+int fn8( int i) {
+ return i;
+}
+
+A fn9() {
+ A a;
+ a.value = 3;
+ return a;
+}
+
+A fn10() {
+ boost::throw_exception( my_exception() );
+ return A();
+}
+
+void fn11( boost::fibers::promise< int > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value(3);
+}
+
+void fn12( boost::fibers::promise< int& > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ gi = 5;
+ p.set_value( gi);
+}
+
+void fn13( boost::fibers::promise< void > p) {
+ boost::this_fiber::sleep_for( ms(500) );
+ p.set_value();
+}
+
+// shared_future
+void test_shared_future_create() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< int > f1;
+ boost::fibers::shared_future< int > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< int > p;
+ boost::fibers::shared_future< int > f1 = p.get_future();
+ boost::fibers::shared_future< int > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_create_ref() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< int& > f1;
+ boost::fibers::shared_future< int& > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< int& > p;
+ boost::fibers::shared_future< int& > f1 = p.get_future();
+ boost::fibers::shared_future< int& > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_create_void() {
+ {
+ // default constructed and assigned shared_future is not valid
+ boost::fibers::shared_future< void > f1;
+ boost::fibers::shared_future< void > f2 = f1;
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+ }
+
+ {
+ // shared_future retrieved from promise is valid
+ boost::fibers::promise< void > p;
+ boost::fibers::shared_future< void > f1 = p.get_future();
+ boost::fibers::shared_future< void > f2 = f1;
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( f2.valid() );
+ }
+}
+
+void test_shared_future_get() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ p1.set_value( 7);
+
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get() );
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_shared_future_get_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ A a; a.value = 7;
+ p1.set_value( std::move( a) );
+
+ boost::fibers::shared_future< A > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ BOOST_CHECK( 7 == f1.get().value);
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< A > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_shared_future_get_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< int& > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+
+void test_shared_future_get_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // get
+ BOOST_CHECK( ! f1.get_exception_ptr() );
+ f1.get();
+ BOOST_CHECK( f1.valid() );
+
+ // throw broken_promise if promise is destroyed without set
+ {
+ boost::fibers::promise< void > p2;
+ f1 = p2.get_future().share();
+ }
+ bool thrown = false;
+ try {
+ f1.get();
+ } catch ( boost::fibers::broken_promise const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( thrown);
+}
+
+void test_future_share() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int j = sf1.get();
+ BOOST_CHECK_EQUAL( i, j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ int i = 7;
+ p1.set_value( i);
+
+ boost::fibers::future< int& > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< int& > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ int & j = sf1.get();
+ BOOST_CHECK( &i == &j);
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_future_share_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ p1.set_value();
+
+ boost::fibers::future< void > f1 = p1.get_future();
+ BOOST_CHECK( f1.valid() );
+
+ // share
+ boost::fibers::shared_future< void > sf1 = f1.share();
+ BOOST_CHECK( sf1.valid() );
+ BOOST_CHECK( ! f1.valid() );
+
+ // get
+ BOOST_CHECK( ! sf1.get_exception_ptr() );
+ sf1.get();
+ BOOST_CHECK( sf1.valid() );
+}
+
+void test_shared_future_wait() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ // wait on future
+ p1.set_value( 7);
+ f1.wait();
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_shared_future_wait_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ // wait on future
+ int i = 7;
+ p1.set_value( i);
+ f1.wait();
+ int & j = f1.get();
+ BOOST_CHECK( &i == &j);
+}
+
+void test_shared_future_wait_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ // wait on future
+ p1.set_value();
+ f1.wait();
+ f1.get();
+ BOOST_CHECK( f1.valid() );
+}
+
+void test_shared_future_wait_for() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_for_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_for_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_for( ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_until_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+
+ boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
+
+ // wait on future
+ BOOST_CHECK( f1.valid() );
+ boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::timeout == status);
+
+ BOOST_CHECK( f1.valid() );
+ status = f1.wait_until( Clock::now() + ms(300) );
+ BOOST_CHECK( boost::fibers::future_status::ready == status);
+
+ BOOST_CHECK( f1.valid() );
+ f1.wait();
+}
+
+void test_shared_future_wait_with_fiber_1() {
+ boost::fibers::promise< int > p1;
+ boost::fibers::fiber( boost::fibers::launch::post, fn1, & p1, 7).detach();
+
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+
+ // wait on future
+ BOOST_CHECK( 7 == f1.get() );
+}
+
+void test_shared_future_wait_with_fiber_2() {
+ boost::fibers::fiber( boost::fibers::launch::post, fn2).join();
+}
+
+void test_shared_future_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int > p1;
+ boost::fibers::shared_future< int > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< int > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_move() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< A > p1;
+ boost::fibers::shared_future< A > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< A > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_ref() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< int& > p1;
+ boost::fibers::shared_future< int& > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< int& > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+void test_shared_future_move_void() {
+ // future retrieved from promise is valid (if it is the first)
+ boost::fibers::promise< void > p1;
+ boost::fibers::shared_future< void > f1 = p1.get_future().share();
+ BOOST_CHECK( f1.valid() );
+
+ // move construction
+ boost::fibers::shared_future< void > f2( std::move( f1) );
+ BOOST_CHECK( ! f1.valid() );
+ BOOST_CHECK( f2.valid() );
+
+ // move assignment
+ f1 = std::move( f2);
+ BOOST_CHECK( f1.valid() );
+ BOOST_CHECK( ! f2.valid() );
+}
+
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
+ boost::unit_test_framework::test_suite* test =
+ BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
+
+ test->add(BOOST_TEST_CASE(test_shared_future_create));
+ test->add(BOOST_TEST_CASE(test_shared_future_create_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_create_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_move_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_get));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_move));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_get_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_for_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_until_void));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1));
+ test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2));
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_unbuffered_channel_dispatch.cpp b/src/boost/libs/fiber/test/test_unbuffered_channel_dispatch.cpp
new file mode 100644
index 00000000..22650576
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_unbuffered_channel_dispatch.cpp
@@ -0,0 +1,451 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 <chrono>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct moveable {
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ other.state = false;
+ value = other.value;
+ other.value = -1;
+ return * this;
+ }
+};
+
+void test_push() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push( 1) );
+}
+
+
+void test_push_wait_for() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_wait_for_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_push_wait_until() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_wait_until_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&v1,&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+}
+
+void test_pop_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&v1,&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop( v2) );
+ f.join();
+}
+
+void test_pop_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ v2 = c.value_pop();
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ int v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+ bool thrown = false;
+ try {
+ c.value_pop();
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_value_pop_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
+ v2 = c.value_pop();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop_wait_for_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_for( v, std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_pop_wait_until() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+}
+
+void test_pop_wait_until_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop_wait_until_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v = 0;
+ BOOST_CHECK(
+ boost::fibers::channel_op_status::timeout == c.pop_wait_until( v,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_wm_1() {
+ boost::fibers::unbuffered_channel< int > c;
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would block because channel is empty
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 12u, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id2, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id2, ids[3]);
+ BOOST_CHECK_EQUAL( id2, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id1, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id1, ids[9]);
+ BOOST_CHECK_EQUAL( id2, ids[10]);
+ BOOST_CHECK_EQUAL( id1, ids[11]);
+}
+
+void test_moveable() {
+ boost::fibers::unbuffered_channel< moveable > c;
+ boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c]{
+ moveable m1( 3);
+ BOOST_CHECK( m1.state);
+ BOOST_CHECK_EQUAL( 3, m1.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( std::move( m1) ) );
+ });
+ moveable m2;
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK_EQUAL( -1, m2.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( m2) );
+ BOOST_CHECK( m2.state);
+ BOOST_CHECK_EQUAL( 3, m2.value);
+ f.join();
+}
+
+void test_rangefor() {
+ boost::fibers::unbuffered_channel< int > chan;
+ std::vector< int > vec;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&chan]{
+ chan.push( 1);
+ chan.push( 1);
+ chan.push( 2);
+ chan.push( 3);
+ chan.push( 5);
+ chan.push( 8);
+ chan.push( 12);
+ chan.close();
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&vec,&chan]{
+ for ( int value : chan) {
+ vec.push_back( value);
+ }
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, vec[0]);
+ BOOST_CHECK_EQUAL( 1, vec[1]);
+ BOOST_CHECK_EQUAL( 2, vec[2]);
+ BOOST_CHECK_EQUAL( 3, vec[3]);
+ BOOST_CHECK_EQUAL( 5, vec[4]);
+ BOOST_CHECK_EQUAL( 8, vec[5]);
+ BOOST_CHECK_EQUAL( 12, vec[6]);
+}
+
+void test_issue_181() {
+ boost::fibers::unbuffered_channel< int > chan;
+ boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&chan]() {
+ auto state = chan.push( 1);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == state);
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&chan]() {
+ boost::this_fiber::sleep_for( std::chrono::milliseconds( 100) );
+ chan.close();
+ });
+ f2.join();
+ f1.join();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: unbuffered_channel test suite");
+
+ test->add( BOOST_TEST_CASE( & test_push) );
+ test->add( BOOST_TEST_CASE( & test_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop) );
+ test->add( BOOST_TEST_CASE( & test_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_value_pop) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_wm_1) );
+ test->add( BOOST_TEST_CASE( & test_moveable) );
+ test->add( BOOST_TEST_CASE( & test_rangefor) );
+ test->add( BOOST_TEST_CASE( & test_issue_181) );
+
+ return test;
+}
diff --git a/src/boost/libs/fiber/test/test_unbuffered_channel_post.cpp b/src/boost/libs/fiber/test/test_unbuffered_channel_post.cpp
new file mode 100644
index 00000000..ff0f01de
--- /dev/null
+++ b/src/boost/libs/fiber/test/test_unbuffered_channel_post.cpp
@@ -0,0 +1,451 @@
+
+// Copyright Oliver Kowalke 2013.
+// Distributed under the 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 <chrono>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/fiber/all.hpp>
+
+struct moveable {
+ bool state;
+ int value;
+
+ moveable() :
+ state( false),
+ value( -1) {
+ }
+
+ moveable( int v) :
+ state( true),
+ value( v) {
+ }
+
+ moveable( moveable && other) :
+ state( other.state),
+ value( other.value) {
+ other.state = false;
+ other.value = -1;
+ }
+
+ moveable & operator=( moveable && other) {
+ if ( this == & other) return * this;
+ state = other.state;
+ other.state = false;
+ value = other.value;
+ other.value = -1;
+ return * this;
+ }
+};
+
+void test_push() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push( 1) );
+}
+
+
+void test_push_wait_for() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_wait_for_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_for_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c](){
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_push_wait_until() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ f.join();
+}
+
+void test_push_wait_until_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ c.close();
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_push_wait_until_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c](){
+ int value = 0;
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
+ BOOST_CHECK_EQUAL( 1, value);
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_until( 1,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&v1,&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+}
+
+void test_pop_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&v1,&c](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop( v2) );
+ f.join();
+}
+
+void test_pop_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ v2 = c.value_pop();
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_value_pop_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ int v2 = c.value_pop();
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+ bool thrown = false;
+ try {
+ c.value_pop();
+ } catch ( boost::fibers::fiber_error const&) {
+ thrown = true;
+ }
+ BOOST_CHECK( thrown);
+}
+
+void test_value_pop_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v2](){
+ v2 = c.value_pop();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop_wait_for_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_for_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v](){
+ BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_for( v, std::chrono::seconds( 1) ) );
+ });
+ f.join();
+}
+
+void test_pop_wait_until() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ f.join();
+}
+
+void test_pop_wait_until_closed() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v1](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ c.close();
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ BOOST_CHECK_EQUAL( v1, v2);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ f.join();
+}
+
+void test_pop_wait_until_success() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v1 = 2, v2 = 0;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c,&v2](){
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+ });
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
+ f.join();
+ BOOST_CHECK_EQUAL( v1, v2);
+}
+
+void test_pop_wait_until_timeout() {
+ boost::fibers::unbuffered_channel< int > c;
+ int v = 0;
+ BOOST_CHECK(
+ boost::fibers::channel_op_status::timeout == c.pop_wait_until( v,
+ std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
+}
+
+void test_wm_1() {
+ boost::fibers::unbuffered_channel< int > c;
+ std::vector< boost::fibers::fiber::id > ids;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would be blocked because channel is full
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&c,&ids](){
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 1, c.value_pop() );
+
+ // let other fiber run
+ boost::this_fiber::yield();
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 2, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 3, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ BOOST_CHECK_EQUAL( 4, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ // would block because channel is empty
+ BOOST_CHECK_EQUAL( 5, c.value_pop() );
+
+ ids.push_back( boost::this_fiber::get_id() );
+ });
+ boost::fibers::fiber::id id1 = f1.get_id();
+ boost::fibers::fiber::id id2 = f2.get_id();
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 12u, ids.size() );
+ BOOST_CHECK_EQUAL( id1, ids[0]);
+ BOOST_CHECK_EQUAL( id2, ids[1]);
+ BOOST_CHECK_EQUAL( id1, ids[2]);
+ BOOST_CHECK_EQUAL( id2, ids[3]);
+ BOOST_CHECK_EQUAL( id2, ids[4]);
+ BOOST_CHECK_EQUAL( id1, ids[5]);
+ BOOST_CHECK_EQUAL( id2, ids[6]);
+ BOOST_CHECK_EQUAL( id1, ids[7]);
+ BOOST_CHECK_EQUAL( id2, ids[8]);
+ BOOST_CHECK_EQUAL( id1, ids[9]);
+ BOOST_CHECK_EQUAL( id2, ids[10]);
+ BOOST_CHECK_EQUAL( id1, ids[11]);
+}
+
+void test_moveable() {
+ boost::fibers::unbuffered_channel< moveable > c;
+ boost::fibers::fiber f( boost::fibers::launch::post, [&c]{
+ moveable m1( 3);
+ BOOST_CHECK( m1.state);
+ BOOST_CHECK_EQUAL( 3, m1.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( std::move( m1) ) );
+ });
+ moveable m2;
+ BOOST_CHECK( ! m2.state);
+ BOOST_CHECK_EQUAL( -1, m2.value);
+ BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( m2) );
+ BOOST_CHECK( m2.state);
+ BOOST_CHECK_EQUAL( 3, m2.value);
+ f.join();
+}
+
+void test_rangefor() {
+ boost::fibers::unbuffered_channel< int > chan;
+ std::vector< int > vec;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&chan]{
+ chan.push( 1);
+ chan.push( 1);
+ chan.push( 2);
+ chan.push( 3);
+ chan.push( 5);
+ chan.push( 8);
+ chan.push( 12);
+ chan.close();
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&vec,&chan]{
+ for ( int value : chan) {
+ vec.push_back( value);
+ }
+ });
+ f1.join();
+ f2.join();
+ BOOST_CHECK_EQUAL( 1, vec[0]);
+ BOOST_CHECK_EQUAL( 1, vec[1]);
+ BOOST_CHECK_EQUAL( 2, vec[2]);
+ BOOST_CHECK_EQUAL( 3, vec[3]);
+ BOOST_CHECK_EQUAL( 5, vec[4]);
+ BOOST_CHECK_EQUAL( 8, vec[5]);
+ BOOST_CHECK_EQUAL( 12, vec[6]);
+}
+
+void test_issue_181() {
+ boost::fibers::unbuffered_channel< int > chan;
+ boost::fibers::fiber f1( boost::fibers::launch::post, [&chan]() {
+ auto state = chan.push( 1);
+ BOOST_CHECK( boost::fibers::channel_op_status::closed == state);
+ });
+ boost::fibers::fiber f2( boost::fibers::launch::post, [&chan]() {
+ boost::this_fiber::sleep_for( std::chrono::milliseconds( 100) );
+ chan.close();
+ });
+ f2.join();
+ f1.join();
+}
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
+ boost::unit_test::test_suite * test =
+ BOOST_TEST_SUITE("Boost.Fiber: unbuffered_channel test suite");
+
+ test->add( BOOST_TEST_CASE( & test_push) );
+ test->add( BOOST_TEST_CASE( & test_push_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_push_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop) );
+ test->add( BOOST_TEST_CASE( & test_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_value_pop) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_closed) );
+ test->add( BOOST_TEST_CASE( & test_value_pop_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_closed) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_success) );
+ test->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout) );
+ test->add( BOOST_TEST_CASE( & test_wm_1) );
+ test->add( BOOST_TEST_CASE( & test_moveable) );
+ test->add( BOOST_TEST_CASE( & test_rangefor) );
+ test->add( BOOST_TEST_CASE( & test_issue_181) );
+
+ return test;
+}