peerplays-fc/include/fc/thread.hpp
Daniel Larimer 25872b11b8 Updated fc::value implementation
Improved fc::value to use enum types instead of strings.
Moved code from header to cpp file
Added extra utility method to simplify syntax for generating key-value pairs for errors/logs.
Removed need to create copies when casting strings, arrays, or objects from values
2013-02-07 16:08:43 -05:00

176 lines
6.2 KiB
C++

#pragma once
#include <fc/task.hpp>
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc {
class time_point;
class microseconds;
class thread {
public:
thread( const char* name = "" );
thread( thread&& m );
thread& operator=(thread&& t );
/**
* Returns the current thread.
*/
static thread& current();
/**
* @brief returns the name given by @ref set_name() for this thread
*/
const string& name()const;
/**
* @brief associates a name with this thread.
*/
void set_name( const string& n );
/**
* @brief print debug info about the state of every context / promise.
*
* This method is helpful to figure out where your program is 'hung' by listing
* every async operation (context) and what it is blocked on (future).
*
* @note debug info is more useful if you provide a description for your
* async tasks and promises.
*/
void debug( const fc::string& d );
/**
* Calls function <code>f</code> in this thread and returns a future<T> that can
* be used to wait on the result.
*
* @param f the operation to perform
* @param prio the priority relative to other tasks
*/
template<typename Functor>
auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> {
typedef decltype(f()) Result;
typedef typename fc::deduce<Functor>::type FunctorType;
fc::task<Result,sizeof(FunctorType)>* tsk =
new fc::task<Result,sizeof(FunctorType)>( fc::forward<Functor>(f) );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
async_task(tsk,prio,desc);
return r;
}
void poke();
/**
* Calls function <code>f</code> in this thread and returns a future<T> that can
* be used to wait on the result.
*
* @param f the method to be called
* @param prio the priority of this method relative to others
* @param when determines when this call will happen, as soon as
* possible after <code>when</code>
*/
template<typename Functor>
auto schedule( Functor&& f, const fc::time_point& when,
const char* desc = "", priority prio = priority()) -> fc::future<decltype(f())> {
typedef decltype(f()) Result;
fc::task<Result,sizeof(Functor)>* tsk =
new fc::task<Result,sizeof(Functor)>( fc::forward<Functor>(f) );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
async_task(tsk,prio,when,desc);
return r;
}
/**
* This method will cancel all pending tasks causing them to throw cmt::error::thread_quit.
*
* If the <i>current</i> thread is not <code>this</code> thread, then the <i>current</i> thread will
* wait for <code>this</code> thread to exit.
*
* This is a blocking wait via <code>boost::thread::join</code>
* and other tasks in the <i>current</i> thread will not run while
* waiting for <code>this</code> thread to quit.
*
* @todo make quit non-blocking of the calling thread by eliminating the call to <code>boost::thread::join</code>
*/
void quit();
/**
* @return true unless quit() has been called.
*/
bool is_running()const;
bool is_current()const;
priority current_priority()const;
~thread();
template<typename T1, typename T2>
int wait_any( const fc::future<T1>& f1, const fc::future<T2>& f2, const microseconds& timeout_us = microseconds::max()) {
fc::vector<fc::promise_base::ptr> proms(2);
proms[0] = fc::static_pointer_cast<fc::promise_base>(f1.m_prom);
proms[1] = fc::static_pointer_cast<fc::promise_base>(f2.m_prom);
return wait_any_until(fc::move(proms), fc::time_point::now()+timeout_us );
}
private:
thread( class thread_d* );
friend class promise_base;
friend class thread_d;
friend class mutex;
friend void yield();
friend void usleep(const microseconds&);
friend void sleep_until(const time_point&);
friend void exec();
friend int wait_any( fc::vector<promise_base::ptr>&& v, const microseconds& );
friend int wait_any_until( fc::vector<promise_base::ptr>&& v, const time_point& tp );
void wait_until( promise_base::ptr && v, const time_point& tp );
void notify( const promise_base::ptr& v );
void yield(bool reschedule=true);
void sleep_until( const time_point& t );
void exec();
int wait_any_until( fc::vector<promise_base::ptr>&& v, const time_point& );
void async_task( task_base* t, const priority& p, const char* desc );
void async_task( task_base* t, const priority& p, const time_point& tp, const char* desc );
class thread_d* my;
};
/**
* Yields to other ready tasks before returning.
*/
void yield();
/**
* Yields to other ready tasks for u microseconds.
*/
void usleep( const microseconds& u );
/**
* Yields until the specified time in the future.
*/
void sleep_until( const time_point& tp );
/**
* Enters the main loop processing tasks until quit() is called.
*/
void exec();
/**
* Wait until either f1 or f2 is ready.
*
* @return 0 if f1 is ready, 1 if f2 is ready or throw on error.
*/
template<typename T1, typename T2>
int wait_any( const fc::future<T1>& f1, const fc::future<T2>& f2, const microseconds timeout_us = microseconds::max()) {
return fc::thread::current().wait_any(f1,f2,timeout_us);
}
int wait_any( fc::vector<promise_base::ptr>&& v, const microseconds& timeout_us = microseconds::max() );
int wait_any_until( fc::vector<promise_base::ptr>&& v, const time_point& tp );
template<typename Functor>
auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> {
return fc::thread::current().async( fc::forward<Functor>(f), desc, prio );
}
}