peerplays-fc/src/future.cpp

94 lines
2.2 KiB
C++
Raw Normal View History

2012-09-08 02:50:37 +00:00
#include <fc/future.hpp>
#include <fc/spin_yield_lock.hpp>
#include <fc/exception.hpp>
#include <fc/thread.hpp>
#include <fc/error.hpp>
#include <fc/unique_lock.hpp>
#include <boost/assert.hpp>
2012-09-09 23:44:49 +00:00
2012-09-08 02:50:37 +00:00
namespace fc {
promise_base::promise_base( const char* desc )
2012-09-09 23:44:49 +00:00
:_ready(false),
2012-09-08 02:50:37 +00:00
_blocked_thread(nullptr),
_timeout(time_point::max()),
_canceled(false),
_desc(desc),
_compl(nullptr)
2012-09-09 23:44:49 +00:00
{ }
2012-09-08 02:50:37 +00:00
const char* promise_base::get_desc()const{
return _desc;
}
void promise_base::cancel(){
_canceled = true;
}
bool promise_base::ready()const {
return _ready;
}
bool promise_base::error()const {
{ synchronized(_spin_yield)
2012-12-03 19:51:31 +00:00
return _exceptp;
2012-09-08 02:50:37 +00:00
}
}
void promise_base::set_exception( const fc::exception_ptr& e ){
2012-12-03 19:51:31 +00:00
_exceptp = e;
2012-09-08 02:50:37 +00:00
_set_value(nullptr);
}
void promise_base::_wait( const microseconds& timeout_us ){
if( timeout_us == microseconds::max() ) _wait_until( time_point::max() );
else _wait_until( time_point::now() + timeout_us );
}
void promise_base::_wait_until( const time_point& timeout_us ){
{ synchronized(_spin_yield)
if( _ready ) {
2012-12-03 19:51:31 +00:00
if( _exceptp ) fc::rethrow_exception( _exceptp );
2012-09-08 02:50:37 +00:00
return;
}
_enqueue_thread();
}
thread::current().wait_until( ptr(this,true), timeout_us );
if( _ready ) {
2012-12-03 19:51:31 +00:00
if( _exceptp ) fc::rethrow_exception( _exceptp );
2012-09-08 02:50:37 +00:00
return;
}
FC_THROW( future_wait_timeout() );
}
void promise_base::_enqueue_thread(){
_blocked_thread =&thread::current();
}
void promise_base::_notify(){
2012-09-09 23:44:49 +00:00
if( _blocked_thread != nullptr )
2012-09-08 02:50:37 +00:00
_blocked_thread->notify(ptr(this,true));
}
2012-09-09 23:44:49 +00:00
promise_base::~promise_base() { }
2012-09-08 02:50:37 +00:00
void promise_base::_set_timeout(){
if( _ready )
return;
set_exception( fc::copy_exception( future_wait_timeout() ) );
}
void promise_base::_set_value(const void* s){
2012-09-09 23:44:49 +00:00
// slog( "%p == %d", &_ready, int(_ready));
// BOOST_ASSERT( !_ready );
2012-09-08 02:50:37 +00:00
{ synchronized(_spin_yield)
_ready = true;
}
_notify();
2012-09-09 23:44:49 +00:00
if( nullptr != _compl ) {
2012-12-03 19:51:31 +00:00
_compl->on_complete(s,_exceptp);
2012-09-08 02:50:37 +00:00
}
}
void promise_base::_on_complete( detail::completion_handler* c ) {
{ synchronized(_spin_yield)
delete _compl;
_compl = c;
}
}
}