2013-06-05 19:19:00 +00:00
|
|
|
#include <fc/thread/task.hpp>
|
|
|
|
|
#include <fc/exception/exception.hpp>
|
|
|
|
|
#include <fc/thread/unique_lock.hpp>
|
|
|
|
|
#include <fc/thread/spin_lock.hpp>
|
|
|
|
|
#include <fc/fwd_impl.hpp>
|
2014-08-01 15:31:36 +00:00
|
|
|
#include "context.hpp"
|
2013-06-05 19:19:00 +00:00
|
|
|
|
|
|
|
|
#include <fc/log/logger.hpp>
|
|
|
|
|
#include <boost/exception/all.hpp>
|
|
|
|
|
|
2014-03-08 23:48:19 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
# include <fc/thread/thread.hpp>
|
|
|
|
|
# include <Windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-06-05 19:19:00 +00:00
|
|
|
namespace fc {
|
|
|
|
|
task_base::task_base(void* func)
|
2014-01-06 22:58:38 +00:00
|
|
|
:
|
2014-07-27 21:37:21 +00:00
|
|
|
promise_base("task_base"),
|
2014-01-06 22:58:38 +00:00
|
|
|
_posted_num(0),
|
|
|
|
|
_active_context(nullptr),
|
|
|
|
|
_next(nullptr),
|
2014-08-27 16:20:19 +00:00
|
|
|
_task_specific_data(nullptr),
|
2014-01-06 22:58:38 +00:00
|
|
|
_promise_impl(nullptr),
|
|
|
|
|
_functor(func){
|
2013-06-05 19:19:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void task_base::run() {
|
2014-03-08 23:48:19 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
__try {
|
|
|
|
|
#endif
|
|
|
|
|
run_impl();
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
} __except (get_unhandled_structured_exception_filter() ? get_unhandled_structured_exception_filter()(GetExceptionCode(), GetExceptionInformation()) : EXCEPTION_CONTINUE_SEARCH) {
|
|
|
|
|
ExitProcess(1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2014-08-01 15:31:36 +00:00
|
|
|
|
2014-03-08 23:48:19 +00:00
|
|
|
void task_base::run_impl() {
|
2013-06-05 19:19:00 +00:00
|
|
|
try {
|
2014-06-29 01:08:15 +00:00
|
|
|
if( !canceled() )
|
|
|
|
|
_run_functor( _functor, _promise_impl );
|
|
|
|
|
else
|
2014-08-28 19:42:01 +00:00
|
|
|
#ifdef NDEBUG
|
|
|
|
|
FC_THROW_EXCEPTION( canceled_exception, "task ${description} canceled before starting", ("description", get_desc()));
|
|
|
|
|
#else
|
|
|
|
|
FC_THROW_EXCEPTION( canceled_exception, "task ${description} canceled before starting, reason ${reason}",
|
|
|
|
|
("description", get_desc())
|
|
|
|
|
("reason", _cancellation_reason ? _cancellation_reason : "[none given]"));
|
|
|
|
|
#endif
|
2013-06-05 19:19:00 +00:00
|
|
|
}
|
|
|
|
|
catch ( const exception& e )
|
|
|
|
|
{
|
|
|
|
|
set_exception( e.dynamic_copy_exception() );
|
|
|
|
|
}
|
|
|
|
|
catch ( ... )
|
|
|
|
|
{
|
|
|
|
|
set_exception( std::make_shared<unhandled_exception>( FC_LOG_MESSAGE( warn, "unhandled exception: ${diagnostic}", ("diagnostic",boost::current_exception_diagnostic_information()) ) ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-01 15:31:36 +00:00
|
|
|
|
2014-08-27 18:07:44 +00:00
|
|
|
void task_base::cancel(const char* reason /* = nullptr */)
|
2014-08-01 15:31:36 +00:00
|
|
|
{
|
2014-08-27 18:07:44 +00:00
|
|
|
promise_base::cancel(reason);
|
2014-08-01 15:31:36 +00:00
|
|
|
if (_active_context)
|
|
|
|
|
{
|
|
|
|
|
_active_context->canceled = true;
|
2014-08-27 18:07:44 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
_active_context->cancellation_reason = reason;
|
|
|
|
|
#endif
|
2014-09-08 14:31:07 +00:00
|
|
|
_active_context->ctx_thread->notify_task_has_been_canceled();
|
2014-08-01 15:31:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 19:19:00 +00:00
|
|
|
task_base::~task_base() {
|
2014-08-27 16:20:19 +00:00
|
|
|
cleanup_task_specific_data();
|
2013-06-05 19:19:00 +00:00
|
|
|
_destroy_functor( _functor );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void task_base::_set_active_context(context* c) {
|
|
|
|
|
{ synchronized( *_spinlock )
|
|
|
|
|
_active_context = c;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-27 16:20:19 +00:00
|
|
|
|
|
|
|
|
void task_base::cleanup_task_specific_data()
|
|
|
|
|
{
|
|
|
|
|
if (_task_specific_data)
|
|
|
|
|
{
|
|
|
|
|
for (auto iter = _task_specific_data->begin(); iter != _task_specific_data->end(); ++iter)
|
|
|
|
|
if (iter->cleanup)
|
|
|
|
|
iter->cleanup(iter->value);
|
|
|
|
|
delete _task_specific_data;
|
|
|
|
|
_task_specific_data = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-05 19:19:00 +00:00
|
|
|
}
|