From c2a37a83bd3f6047440e0d236a5b35ea78acb583 Mon Sep 17 00:00:00 2001 From: Anton Autushka Date: Thu, 9 Nov 2017 15:18:58 +0300 Subject: [PATCH 1/2] Boost 1.61 compatibility fix --- src/thread/context.hpp | 16 +++++- src/thread/thread_d.hpp | 22 +++++++- tests/CMakeLists.txt | 1 + tests/thread/thread_tests.cpp | 95 +++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 tests/thread/thread_tests.cpp diff --git a/src/thread/context.hpp b/src/thread/context.hpp index f6e8a77..221df76 100644 --- a/src/thread/context.hpp +++ b/src/thread/context.hpp @@ -6,7 +6,14 @@ #include -#if BOOST_VERSION >= 105400 +#define BOOST_COROUTINES_NO_DEPRECATION_WARNING + +#if BOOST_VERSION >= 106100 + #include + namespace bc = boost::context::detail; + namespace bco = boost::coroutines; + typedef bco::stack_allocator stack_allocator; +#elif BOOST_VERSION >= 105400 # include namespace bc = boost::context; namespace bco = boost::coroutines; @@ -47,8 +54,13 @@ namespace fc { bco::stack_context stack_ctx; #endif +#if BOOST_VERSION >= 106100 + using context_fn = void (*)(bc::transfer_t); +#else + using context_fn = void(*)(intptr_t); +#endif - context( void (*sf)(intptr_t), stack_allocator& alloc, fc::thread* t ) + context( context_fn sf, stack_allocator& alloc, fc::thread* t ) : caller_context(0), stack_alloc(&alloc), next_blocked(0), diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 941b2fa..6ad9421 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -18,6 +18,8 @@ namespace fc { class thread_d { public: + using context_pair = std::pair; + thread_d(fc::thread& s) :self(s), boost_thread(0), task_in_queue(0), @@ -397,7 +399,11 @@ namespace fc { } // slog( "jump to %p from %p", next, prev ); // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); -#if BOOST_VERSION >= 105600 +#if BOOST_VERSION >= 106100 + auto p = context_pair{nullptr, prev}; + auto t = bc::jump_fcontext( next->my_context, &p ); + static_cast(t.data)->second->my_context = t.fctx; +#elif BOOST_VERSION >= 105600 bc::jump_fcontext( &prev->my_context, next->my_context, 0 ); #elif BOOST_VERSION >= 105300 bc::jump_fcontext( prev->my_context, next->my_context, 0 ); @@ -439,7 +445,11 @@ namespace fc { // slog( "jump to %p from %p", next, prev ); // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); -#if BOOST_VERSION >= 105600 +#if BOOST_VERSION >= 106100 + auto p = context_pair{this, prev}; + auto t = bc::jump_fcontext( next->my_context, &p ); + static_cast(t.data)->second->my_context = t.fctx; +#elif BOOST_VERSION >= 105600 bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this ); #elif BOOST_VERSION >= 105300 bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this ); @@ -467,9 +477,17 @@ namespace fc { return true; } +#if BOOST_VERSION >= 106100 + static void start_process_tasks( bc::transfer_t my ) + { + auto p = static_cast(my.data); + auto self = static_cast(p->first); + p->second->my_context = my.fctx; +#else static void start_process_tasks( intptr_t my ) { thread_d* self = (thread_d*)my; +#endif try { self->process_tasks(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1043e50..f5d5a24 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -51,6 +51,7 @@ add_executable( all_tests all_tests.cpp crypto/sha_tests.cpp network/http/websocket_test.cpp thread/task_cancel.cpp + thread/thread_tests.cpp bloom_test.cpp real128_test.cpp utf8_test.cpp diff --git a/tests/thread/thread_tests.cpp b/tests/thread/thread_tests.cpp new file mode 100644 index 0000000..a1f3d1b --- /dev/null +++ b/tests/thread/thread_tests.cpp @@ -0,0 +1,95 @@ + +#include + +#include + +using namespace fc; + +BOOST_AUTO_TEST_SUITE(thread_tests) + +BOOST_AUTO_TEST_CASE(executes_task) +{ + bool called = false; + fc::thread thread("my"); + thread.async([&called]{called = true;}).wait(); + BOOST_CHECK(called); +} + +BOOST_AUTO_TEST_CASE(returns_value_from_function) +{ + fc::thread thread("my"); + BOOST_CHECK_EQUAL(10, thread.async([]{return 10;}).wait()); +} + +BOOST_AUTO_TEST_CASE(executes_multiple_tasks) +{ + bool called1 = false; + bool called2 = false; + + fc::thread thread("my"); + auto future1 = thread.async([&called1]{called1 = true;}); + auto future2 = thread.async([&called2]{called2 = true;}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK(called1); + BOOST_CHECK(called2); +} + +BOOST_AUTO_TEST_CASE(calls_tasks_in_order) +{ + std::string result; + + fc::thread thread("my"); + auto future1 = thread.async([&result]{result += "hello ";}); + auto future2 = thread.async([&result]{result += "world";}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK_EQUAL("hello world", result); +} + +BOOST_AUTO_TEST_CASE(yields_execution) +{ + std::string result; + + fc::thread thread("my"); + auto future1 = thread.async([&result]{fc::yield(); result += "world";}); + auto future2 = thread.async([&result]{result += "hello ";}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK_EQUAL("hello world", result); +} + +BOOST_AUTO_TEST_CASE(quits_infinite_loop) +{ + fc::thread thread("my"); + auto f = thread.async([]{while (true) fc::yield();}); + + thread.quit(); + BOOST_CHECK_THROW(f.wait(), fc::canceled_exception); +} + +BOOST_AUTO_TEST_CASE(reschedules_yielded_task) +{ + int reschedule_count = 0; + + fc::thread thread("my"); + auto future = thread.async([&reschedule_count] + { + while (reschedule_count < 10) + { + fc::yield(); + reschedule_count++; + } + }); + + future.wait(); + BOOST_CHECK_EQUAL(10, reschedule_count); +} + +BOOST_AUTO_TEST_SUITE_END() From 20836338d2cfb79620b5254c587a806d5e4469e8 Mon Sep 17 00:00:00 2001 From: Anton Autushka Date: Thu, 9 Nov 2017 15:41:44 +0300 Subject: [PATCH 2/2] Suppress coroutines deprecation warning in boost 1.62 --- src/thread/context.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/thread/context.hpp b/src/thread/context.hpp index 221df76..18a060c 100644 --- a/src/thread/context.hpp +++ b/src/thread/context.hpp @@ -6,7 +6,8 @@ #include -#define BOOST_COROUTINES_NO_DEPRECATION_WARNING +#define BOOST_COROUTINES_NO_DEPRECATION_WARNING // Boost 1.61 +#define BOOST_COROUTINE_NO_DEPRECATION_WARNING // Boost 1.62 #if BOOST_VERSION >= 106100 #include