BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
thread.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #define FC_CONTEXT_STACK_SIZE (2048*1024)
4 
5 #include <fc/thread/task.hpp>
6 
7 namespace fc {
8  class time_point;
9  class microseconds;
10 
11  namespace detail
12  {
13  class worker_pool;
14  void* get_thread_specific_data(unsigned slot);
15  void set_thread_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
17  void* get_task_specific_data(unsigned slot);
18  void set_task_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
19  }
20 
25  public:
26  virtual ~thread_idle_notifier() {}
27 
32  virtual task_base* idle() = 0;
36  virtual void busy() = 0;
37  };
38 
39  class thread {
40  public:
41  thread( const std::string& name = "", thread_idle_notifier* notifier = 0 );
42  thread( thread&& m ) = delete;
43  thread& operator=(thread&& t ) = delete;
44 
51  static thread& current();
52  static void cleanup();
53 
54 
58  const string& name()const;
59 
63  void set_name( const string& n );
64 
65  const char* current_task_desc() const;
66 
76  void debug( const std::string& d );
77 
78 
86  template<typename Functor>
87  auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
88  typedef decltype(f()) Result;
89  typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
90  typename task<Result,sizeof(FunctorType)>::ptr tsk =
91  task<Result,sizeof(FunctorType)>::create( std::forward<Functor>(f), desc );
92  tsk->retain(); // HERE BE DRAGONS
93  fc::future<Result> r( std::dynamic_pointer_cast< promise<Result> >(tsk) );
94  async_task(tsk.get(),prio);
95  return r;
96  }
97  void poke();
98 
99 
109  template<typename Functor>
110  auto schedule( Functor&& f, const fc::time_point& when,
111  const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
112  typedef decltype(f()) Result;
113  typename task<Result,sizeof(Functor)>::ptr tsk =
114  task<Result,sizeof(Functor)>::create( std::forward<Functor>(f), desc );
115  tsk->retain(); // HERE BE DRAGONS
116  fc::future<Result> r( std::dynamic_pointer_cast< promise<Result> >(tsk) );
117  async_task(tsk.get(),prio,when);
118  return r;
119  }
120 
133  void quit();
134 
138  void signal(int);
139 
143  bool is_running()const;
144  bool is_current()const;
145 
146  priority current_priority()const;
147  ~thread();
148 
149  template<typename T1, typename T2>
150  int wait_any( const fc::future<T1>& f1, const fc::future<T2>& f2, const microseconds& timeout_us = microseconds::maximum()) {
151  std::vector<fc::promise_base::ptr> proms(2);
152  proms[0] = std::static_pointer_cast<fc::promise_base>(f1.m_prom);
153  proms[1] = std::static_pointer_cast<fc::promise_base>(f2.m_prom);
154  return wait_any_until(std::move(proms), fc::time_point::now()+timeout_us );
155  }
156  private:
157  thread( class thread_d* ); // parameter is ignored, will create a new thread_d
158  friend class promise_base;
159  friend class task_base;
160  friend class thread_d;
161  friend class mutex;
162  friend class detail::worker_pool;
163  friend void* detail::get_thread_specific_data(unsigned slot);
164  friend void detail::set_thread_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
166  friend void* detail::get_task_specific_data(unsigned slot);
167  friend void detail::set_task_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
168 #ifndef NDEBUG
170 #endif
171  friend void yield();
172  friend void usleep(const microseconds&);
173  friend void sleep_until(const time_point&);
174  friend void exec();
175  friend int wait_any( std::vector<promise_base::ptr>&& v, const microseconds& );
176  friend int wait_any_until( std::vector<promise_base::ptr>&& v, const time_point& tp );
177  void wait_until( promise_base::ptr && v, const time_point& tp );
178  void notify( const promise_base::ptr& v );
179 
180  void yield(bool reschedule=true);
181  void sleep_until( const time_point& t );
182  void exec();
183  int wait_any_until( std::vector<promise_base::ptr>&& v, const time_point& );
184 
185  void async_task( task_base* t, const priority& p );
186  void async_task( task_base* t, const priority& p, const time_point& tp );
187 
188  void notify_task_has_been_canceled();
189  void unblock(fc::context* c);
190 
191  class thread_d* my;
192  };
193 
197  void yield();
198 
202  void usleep( const microseconds& u );
203 
207  void sleep_until( const time_point& tp );
208 
212  void exec();
213 
219  template<typename T1, typename T2>
220  int wait_any( const fc::future<T1>& f1, const fc::future<T2>& f2, const microseconds timeout_us = microseconds::maximum()) {
221  return fc::thread::current().wait_any(f1,f2,timeout_us);
222  }
223  int wait_any( std::vector<promise_base::ptr>&& v, const microseconds& timeout_us = microseconds::maximum() );
224  int wait_any_until( std::vector<promise_base::ptr>&& v, const time_point& tp );
225 
226  template<typename Functor>
227  auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
228  return fc::thread::current().async( std::forward<Functor>(f), desc, prio );
229  }
230  template<typename Functor>
231  auto schedule( Functor&& f, const fc::time_point& t, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
232  return fc::thread::current().schedule( std::forward<Functor>(f), t, desc, prio );
233  }
234 
240  template<typename Functor>
241  auto sync_call( thread* t, Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> decltype(f())
242  {
243  if( t == nullptr )
244  return f();
245 
246  typedef decltype(f()) Result;
247  future<Result> r = t->async( f, desc, prio );
248  return r.wait();
249  }
250 
251 } // end namespace fc
252 
253 #ifdef _MSC_VER
254 struct _EXCEPTION_POINTERS;
255 
256 namespace fc {
257  /* There's something about the setup of the stacks created for fc::async tasks
258  * that screws up the global structured exception filters installed by
259  * SetUnhandledExceptionFilter(). The only way I've found to catch an
260  * unhaldned structured exception thrown in an async task is to put a
261  * __try/__except block inside the async task.
262  * We do just that, and if a SEH escapes outside the function running
263  * in the async task, fc will call an exception filter privided by
264  * set_unhandled_structured_exception_filter(), passing as arguments
265  * the result of GetExceptionCode() and GetExceptionInformation().
266  *
267  * Right now there is only one global exception filter, used for any
268  * async task.
269  */
270  typedef int (*unhandled_exception_filter_type)(unsigned, _EXCEPTION_POINTERS*);
271  void set_unhandled_structured_exception_filter(unhandled_exception_filter_type new_filter);
272  unhandled_exception_filter_type get_unhandled_structured_exception_filter();
273 }
274 #endif
275 
fc::promise
Definition: future.hpp:109
fc::thread::current
static thread & current()
Definition: thread.cpp:125
task.hpp
fc::exec
void exec()
Definition: thread.cpp:375
fc::future
a placeholder for the result of an asynchronous operation.
Definition: future.hpp:211
fc::thread::thread
thread(const std::string &name="", thread_idle_notifier *notifier=0)
Definition: thread.cpp:74
fc::detail::get_task_specific_data
void * get_task_specific_data(unsigned slot)
Definition: thread_specific.cpp:41
fc::yield
void yield()
Definition: thread.cpp:365
fc::thread::set_name
void set_name(const string &n)
associates a name with this thread.
Definition: thread.cpp:143
fc::wait_any_until
int wait_any_until(std::vector< promise_base::ptr > &&v, const time_point &tp)
Definition: thread.cpp:385
fc::detail::set_task_specific_data
void set_task_specific_data(unsigned slot, void *new_value, void(*cleanup)(void *))
Definition: thread_specific.cpp:51
fc::mutex
mutex
Definition: mutex.hpp:91
fc::thread::exec
friend void exec()
Definition: thread.cpp:375
fc::detail::get_next_unused_task_storage_slot
unsigned get_next_unused_task_storage_slot()
Definition: thread_specific.cpp:37
fc
Definition: api.hpp:15
fc::thread::schedule
auto schedule(Functor &&f, const fc::time_point &when, const char *desc FC_TASK_NAME_DEFAULT_ARG, priority prio=priority()) -> fc::future< decltype(f())>
Definition: thread.hpp:110
fc::thread_d
Definition: thread_d.hpp:30
fc::thread::debug
void debug(const std::string &d)
print debug info about the state of every context / promise.
Definition: thread.cpp:161
fc::thread_idle_notifier::busy
virtual void busy()=0
fc::thread::yield
friend void yield()
Definition: thread.cpp:365
fc::schedule
auto schedule(Functor &&f, const fc::time_point &t, const char *desc FC_TASK_NAME_DEFAULT_ARG, priority prio=priority()) -> fc::future< decltype(f())>
Definition: thread.hpp:231
fc::usleep
void usleep(const microseconds &u)
Definition: thread.cpp:368
fc::microseconds::maximum
static microseconds maximum()
Definition: time.hpp:15
fc::detail::worker_pool
Definition: parallel.hpp:38
fc::thread_idle_notifier::idle
virtual task_base * idle()=0
fc::context
Definition: context.hpp:47
fc::thread::current_task_desc
const char * current_task_desc() const
Definition: thread.cpp:154
fc::detail::get_thread_specific_data
void * get_thread_specific_data(unsigned slot)
Definition: thread_specific.cpp:28
fc::thread::sleep_until
friend void sleep_until(const time_point &)
Definition: thread.cpp:371
fc::thread::current_priority
priority current_priority() const
Definition: thread.cpp:269
fc::thread
Definition: thread.hpp:39
FC_TASK_NAME_DEFAULT_ARG
#define FC_TASK_NAME_DEFAULT_ARG
Definition: future.hpp:14
fc::async
auto async(Functor &&f, const char *desc FC_TASK_NAME_DEFAULT_ARG, priority prio=priority()) -> fc::future< decltype(f())>
Definition: thread.hpp:227
fc::task_base
Definition: task.hpp:33
fc::sync_call
auto sync_call(thread *t, Functor &&f, const char *desc FC_TASK_NAME_DEFAULT_ARG, priority prio=priority()) -> decltype(f())
Definition: thread.hpp:241
fc::thread::is_running
bool is_running() const
Definition: thread.cpp:264
fc::thread_idle_notifier::~thread_idle_notifier
virtual ~thread_idle_notifier()
Definition: thread.hpp:26
fc::thread::wait_any
int wait_any(const fc::future< T1 > &f1, const fc::future< T2 > &f2, const microseconds &timeout_us=microseconds::maximum())
Definition: thread.hpp:150
fc::microseconds
Definition: time.hpp:12
fc::time_point::now
static time_point now()
Definition: time.cpp:13
fc::thread::quit
void quit()
Definition: thread.cpp:174
fc::priority
Definition: priority.hpp:9
fc::time_point
Definition: time.hpp:44
fc::promise_base
Definition: future.hpp:61
fc::future::wait
const T & wait(const microseconds &timeout=microseconds::maximum()) const
Definition: future.hpp:228
fc::thread::operator=
thread & operator=(thread &&t)=delete
fc::promise_base::ptr
std::shared_ptr< promise_base > ptr
Definition: future.hpp:63
fc::task
Definition: task.hpp:116
fc::thread::cleanup
static void cleanup()
Definition: thread.cpp:131
fc::thread::async
auto async(Functor &&f, const char *desc FC_TASK_NAME_DEFAULT_ARG, priority prio=priority()) -> fc::future< decltype(f())>
Definition: thread.hpp:87
fc::thread_idle_notifier
Definition: thread.hpp:24
fc::detail::set_thread_specific_data
void set_thread_specific_data(unsigned slot, void *new_value, void(*cleanup)(void *))
Definition: thread_specific.cpp:32
fc::wait_any
int wait_any(const fc::future< T1 > &f1, const fc::future< T2 > &f2, const microseconds timeout_us=microseconds::maximum())
Definition: thread.hpp:220
fc::sleep_until
void sleep_until(const time_point &tp)
Definition: thread.cpp:371
fc::thread::signal
void signal(int)
Definition: thread.cpp:167
fc::thread::is_current
bool is_current() const
Definition: thread.cpp:479
fc::thread::~thread
~thread()
Definition: thread.cpp:116
fc::thread::name
const string & name() const
returns the name given by set_name() for this thread
Definition: thread.cpp:138
fc::thread::poke
void poke()
Definition: thread.cpp:340
fc::non_preemptable_scope_check
Definition: non_preemptable_scope_check.hpp:27
fc::thread::wait_any_until
friend int wait_any_until(std::vector< promise_base::ptr > &&v, const time_point &tp)
Definition: thread.cpp:385
fc::thread::usleep
friend void usleep(const microseconds &)
Definition: thread.cpp:368