Add support for boost 1.56.
This commit is contained in:
parent
9b6facea3f
commit
454573e048
6 changed files with 105 additions and 39 deletions
|
|
@ -1,9 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <boost/signals2/signal.hpp>
|
#include <boost/signals2/signal.hpp>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <fc/thread/future.hpp>
|
#include <fc/thread/future.hpp>
|
||||||
#include <fc/thread/thread.hpp>
|
#include <fc/thread/thread.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
|
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -37,4 +47,3 @@ namespace fc {
|
||||||
p->wait( timeout_us );
|
p->wait( timeout_us );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
namespace boost {
|
|
||||||
template<typename T> class atomic;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
class microseconds;
|
class microseconds;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
template<typename T> class atomic;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
class microseconds;
|
class microseconds;
|
||||||
class time_point;
|
class time_point;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,18 @@
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
#if BOOST_VERSION >= 105400
|
#if BOOST_VERSION >= 105400
|
||||||
#include <boost/coroutine/stack_context.hpp>
|
# include <boost/coroutine/stack_context.hpp>
|
||||||
#include <boost/coroutine/stack_allocator.hpp>
|
|
||||||
namespace bc = boost::context;
|
namespace bc = boost::context;
|
||||||
namespace bco = boost::coroutines;
|
namespace bco = boost::coroutines;
|
||||||
|
# if BOOST_VERSION >= 105600 && !defined(NDEBUG)
|
||||||
|
# include <boost/assert.hpp>
|
||||||
|
# include <boost/coroutine/protected_stack_allocator.hpp>
|
||||||
|
typedef bco::protected_stack_allocator stack_allocator;
|
||||||
|
# else
|
||||||
|
# include <boost/coroutine/stack_allocator.hpp>
|
||||||
|
typedef bco::stack_allocator stack_allocator;
|
||||||
|
# endif
|
||||||
|
|
||||||
#elif BOOST_VERSION >= 105300
|
#elif BOOST_VERSION >= 105300
|
||||||
#include <boost/coroutine/stack_allocator.hpp>
|
#include <boost/coroutine/stack_allocator.hpp>
|
||||||
namespace bc = boost::context;
|
namespace bc = boost::context;
|
||||||
|
|
@ -35,12 +43,12 @@ namespace fc {
|
||||||
struct context {
|
struct context {
|
||||||
typedef fc::context* ptr;
|
typedef fc::context* ptr;
|
||||||
|
|
||||||
#if BOOST_VERSION >= 105400
|
#if BOOST_VERSION >= 105400
|
||||||
bco::stack_context stack_ctx;
|
bco::stack_context stack_ctx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
context( void (*sf)(intptr_t), bco::stack_allocator& alloc, fc::thread* t )
|
context( void (*sf)(intptr_t), stack_allocator& alloc, fc::thread* t )
|
||||||
: caller_context(0),
|
: caller_context(0),
|
||||||
stack_alloc(&alloc),
|
stack_alloc(&alloc),
|
||||||
next_blocked(0),
|
next_blocked(0),
|
||||||
|
|
@ -54,7 +62,11 @@ namespace fc {
|
||||||
complete(false),
|
complete(false),
|
||||||
cur_task(0)
|
cur_task(0)
|
||||||
{
|
{
|
||||||
#if BOOST_VERSION >= 105400
|
#if BOOST_VERSION >= 105600
|
||||||
|
size_t stack_size = stack_allocator::traits_type::default_size() * 4;
|
||||||
|
alloc.allocate(stack_ctx, stack_size);
|
||||||
|
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
||||||
|
#elif BOOST_VERSION >= 105400
|
||||||
size_t stack_size = bco::stack_allocator::default_stacksize() * 4;
|
size_t stack_size = bco::stack_allocator::default_stacksize() * 4;
|
||||||
alloc.allocate(stack_ctx, stack_size);
|
alloc.allocate(stack_ctx, stack_size);
|
||||||
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
||||||
|
|
@ -71,7 +83,9 @@ namespace fc {
|
||||||
}
|
}
|
||||||
|
|
||||||
context( fc::thread* t) :
|
context( fc::thread* t) :
|
||||||
#if BOOST_VERSION >= 105300
|
#if BOOST_VERSION >= 105600
|
||||||
|
my_context(nullptr),
|
||||||
|
#elif BOOST_VERSION >= 105300
|
||||||
my_context(new bc::fcontext_t),
|
my_context(new bc::fcontext_t),
|
||||||
#endif
|
#endif
|
||||||
caller_context(0),
|
caller_context(0),
|
||||||
|
|
@ -89,20 +103,17 @@ namespace fc {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~context() {
|
~context() {
|
||||||
#if BOOST_VERSION >= 105400
|
#if BOOST_VERSION >= 105600
|
||||||
|
if(stack_alloc)
|
||||||
|
stack_alloc->deallocate( stack_ctx );
|
||||||
|
#elif BOOST_VERSION >= 105400
|
||||||
if(stack_alloc)
|
if(stack_alloc)
|
||||||
stack_alloc->deallocate( stack_ctx );
|
stack_alloc->deallocate( stack_ctx );
|
||||||
else
|
else
|
||||||
delete my_context;
|
delete my_context;
|
||||||
#elif BOOST_VERSION >= 105400
|
|
||||||
if(stack_alloc)
|
|
||||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() * 4 );
|
|
||||||
else
|
|
||||||
delete my_context;
|
|
||||||
|
|
||||||
#elif BOOST_VERSION >= 105300
|
#elif BOOST_VERSION >= 105300
|
||||||
if(stack_alloc)
|
if(stack_alloc)
|
||||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() * 4);
|
stack_alloc->deallocate( my_context->fc_stack.sp, stack_allocator::default_stacksize() * 4);
|
||||||
else
|
else
|
||||||
delete my_context;
|
delete my_context;
|
||||||
#else
|
#else
|
||||||
|
|
@ -196,13 +207,13 @@ namespace fc {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if BOOST_VERSION >= 105300
|
#if BOOST_VERSION >= 105300 && BOOST_VERSION < 105600
|
||||||
bc::fcontext_t* my_context;
|
bc::fcontext_t* my_context;
|
||||||
#else
|
#else
|
||||||
bc::fcontext_t my_context;
|
bc::fcontext_t my_context;
|
||||||
#endif
|
#endif
|
||||||
fc::context* caller_context;
|
fc::context* caller_context;
|
||||||
bco::stack_allocator* stack_alloc;
|
stack_allocator* stack_alloc;
|
||||||
priority prio;
|
priority prio;
|
||||||
//promise_base* prom;
|
//promise_base* prom;
|
||||||
std::vector<blocked_promise> blocking_prom;
|
std::vector<blocked_promise> blocking_prom;
|
||||||
|
|
|
||||||
|
|
@ -68,26 +68,26 @@ namespace fc {
|
||||||
}
|
}
|
||||||
fc::thread& self;
|
fc::thread& self;
|
||||||
boost::thread* boost_thread;
|
boost::thread* boost_thread;
|
||||||
bco::stack_allocator stack_alloc;
|
stack_allocator stack_alloc;
|
||||||
boost::condition_variable task_ready;
|
boost::condition_variable task_ready;
|
||||||
boost::mutex task_ready_mutex;
|
boost::mutex task_ready_mutex;
|
||||||
|
|
||||||
boost::atomic<task_base*> task_in_queue;
|
boost::atomic<task_base*> task_in_queue;
|
||||||
std::vector<task_base*> task_pqueue;
|
std::vector<task_base*> task_pqueue; // heap of tasks that have never started, ordered by proirity & scheduling time
|
||||||
std::vector<task_base*> task_sch_queue;
|
std::vector<task_base*> task_sch_queue; // heap of tasks that have never started but are scheduled for a time in the future, ordered by the time they should be run
|
||||||
std::vector<fc::context*> sleep_pqueue;
|
std::vector<fc::context*> sleep_pqueue; // heap of running tasks that have sleeped, ordered by the time they should resume
|
||||||
std::vector<fc::context*> free_list;
|
std::vector<fc::context*> free_list; // list of unused contexts that are ready for deletion
|
||||||
|
|
||||||
bool done;
|
bool done;
|
||||||
fc::string name;
|
fc::string name;
|
||||||
fc::context* current;
|
fc::context* current; // the currently-executing task in this thread
|
||||||
|
|
||||||
fc::context* pt_head;
|
fc::context* pt_head; // list of contexts that can be reused for new tasks
|
||||||
|
|
||||||
fc::context* ready_head;
|
fc::context* ready_head; // linked list (using 'next') of contexts that are ready to run
|
||||||
fc::context* ready_tail;
|
fc::context* ready_tail;
|
||||||
|
|
||||||
fc::context* blocked;
|
fc::context* blocked; // linked list of contexts (using 'next_blocked') blocked on promises via wait()
|
||||||
|
|
||||||
// values for thread specific data objects for this thread
|
// values for thread specific data objects for this thread
|
||||||
std::vector<detail::specific_data_info> thread_specific_data;
|
std::vector<detail::specific_data_info> thread_specific_data;
|
||||||
|
|
@ -321,8 +321,10 @@ namespace fc {
|
||||||
current = next;
|
current = next;
|
||||||
if( reschedule ) ready_push_back(prev);
|
if( reschedule ) ready_push_back(prev);
|
||||||
// slog( "jump to %p from %p", next, prev );
|
// 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) ) );
|
// fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) );
|
||||||
#if BOOST_VERSION >= 105300
|
#if 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 );
|
bc::jump_fcontext( prev->my_context, next->my_context, 0 );
|
||||||
#else
|
#else
|
||||||
bc::jump_fcontext( &prev->my_context, &next->my_context, 0 );
|
bc::jump_fcontext( &prev->my_context, &next->my_context, 0 );
|
||||||
|
|
@ -350,7 +352,9 @@ namespace fc {
|
||||||
|
|
||||||
// slog( "jump to %p from %p", next, prev );
|
// 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) ) );
|
// fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) );
|
||||||
#if BOOST_VERSION >= 105300
|
#if 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 );
|
bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this );
|
||||||
#else
|
#else
|
||||||
bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this );
|
bc::jump_fcontext( &prev->my_context, &next->my_context, (intptr_t)this );
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE( test_non_preemptable_assertion )
|
||||||
BOOST_TEST_PASSPOINT();
|
BOOST_TEST_PASSPOINT();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( cancel_an_active_task )
|
BOOST_AUTO_TEST_CASE( cancel_an_sleeping_task )
|
||||||
{
|
{
|
||||||
enum task_result{sleep_completed, sleep_aborted};
|
enum task_result{sleep_completed, sleep_aborted};
|
||||||
fc::future<task_result> task = fc::async([]() {
|
fc::future<task_result> task = fc::async([]() {
|
||||||
|
|
@ -128,6 +128,55 @@ BOOST_AUTO_TEST_CASE( cancel_an_active_task )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( cancel_a_task_waiting_on_promise )
|
||||||
|
{
|
||||||
|
enum task_result{task_completed, task_aborted};
|
||||||
|
|
||||||
|
fc::promise<void>::ptr promise_to_wait_on(new fc::promise<void>());
|
||||||
|
|
||||||
|
fc::future<task_result> task = fc::async([promise_to_wait_on]() {
|
||||||
|
BOOST_TEST_MESSAGE("Starting async task");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
promise_to_wait_on->wait_until(fc::time_point::now() + fc::seconds(5));
|
||||||
|
return task_completed;
|
||||||
|
}
|
||||||
|
catch (const fc::canceled_exception&)
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Caught canceled_exception inside task-to-be-canceled");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (const fc::timeout_exception&)
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Caught timeout_exception inside task-to-be-canceled");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (const fc::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Caught unexpected exception inside task-to-be-canceled: " << e.to_detail_string());
|
||||||
|
return task_aborted;
|
||||||
|
}
|
||||||
|
}, "test_task");
|
||||||
|
|
||||||
|
fc::time_point start_time = fc::time_point::now();
|
||||||
|
|
||||||
|
// wait a bit for the task to start running
|
||||||
|
fc::usleep(fc::milliseconds(100));
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Canceling task");
|
||||||
|
task.cancel("canceling to test if cancel works");
|
||||||
|
//promise_to_wait_on->set_value();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
task_result result = task.wait();
|
||||||
|
BOOST_CHECK_MESSAGE(result != task_completed, "task should have been canceled");
|
||||||
|
}
|
||||||
|
catch (fc::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Caught exception from canceled task: " << e.what());
|
||||||
|
BOOST_CHECK_MESSAGE(fc::time_point::now() - start_time < fc::seconds(4), "Task was not canceled quickly");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( cleanup_cancelled_task )
|
BOOST_AUTO_TEST_CASE( cleanup_cancelled_task )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue