BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
task.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <fc/thread/future.hpp>
3 #include <fc/thread/priority.hpp>
4 #include <fc/fwd.hpp>
5 #include <type_traits>
6 
7 #include <boost/atomic.hpp>
8 
9 namespace fc {
10  struct context;
11  class spin_lock;
12 
13  namespace detail
14  {
16  {
17  void* value;
18  void (*cleanup)(void*);
20  value(0),
21  cleanup(0)
22  {}
23  specific_data_info(void* value, void (*cleanup)(void*)) :
24  value(value),
26  {}
27  };
28  void* get_task_specific_data(unsigned slot);
29  void set_task_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
30  class idle_guard;
31  }
32 
33  class task_base : virtual public promise_base {
34  public:
35  void run();
36  virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override;
37  virtual ~task_base();
38 
39  /* HERE BE DRAGONS
40  *
41  * Tasks are handled by an fc::thread . To avoid concurrency issues, fc::thread keeps a reference to the
42  * task in the form of a simple pointer.
43  * At the same time, a task is also a promise that will be fulfilled with the task result, so typically the
44  * creator of the task also keeps a reference to the task (but not necessarily always).
45  *
46  * Because effectively neither fc::thread nor the task creator are responsible for releasing resources
47  * associated with a task, and neither can delete the task without knowing if the other still needs it,
48  * the task object is managed by a shared_ptr.
49  * However, fc::thread doesn't hold a shared_ptr but a native pointer. To work around this, the task can
50  * be made to contain a shared_ptr holding itself (by calling retain()), which happens before the task
51  * is handed to an fc::thread, e. g. in fc::async(). Once the thread has processed the task, it calls
52  * release() which deletes the self-referencing shared_ptr and deletes the task object if it's no longer
53  * in use anywhere.
54  */
55  void retain();
56  void release();
57 
58  protected:
60  uint64_t _posted_num;
66 
67  // support for task-specific data
68  std::vector<detail::specific_data_info> *_task_specific_data;
69 
70  friend void* detail::get_task_specific_data(unsigned slot);
71  friend void detail::set_task_specific_data(unsigned slot, void* new_value, void(*cleanup)(void*));
72 
73  task_base(void* func);
74  // opaque internal / private data used by
75  // thread/thread_private
76  friend class thread;
77  friend class thread_d;
78  friend class detail::idle_guard;
80 
81  // avoid rtti info for every possible functor...
83  void* _functor;
84  void (*_destroy_functor)(void*);
85  void (*_run_functor)(void*, void* );
86 
87  void run_impl();
88 
90  private:
91  std::shared_ptr<promise_base> _self;
92  boost::atomic<int32_t> _retain_count;
93  };
94 
95  namespace detail {
96  template<typename T>
98  static void destroy( void* v ) { ((T*)v)->~T(); }
99  };
100  template<typename T>
101  struct functor_run {
102  static void run( void* functor, void* prom ) {
103  ((promise<decltype((*((T*)functor))())>*)prom)->set_value( (*((T*)functor))() );
104  }
105  };
106  template<typename T>
108  static void run( void* functor, void* prom ) {
109  (*((T*)functor))();
110  ((promise<void>*)prom)->set_value();
111  }
112  };
113  }
114 
115  template<typename R,uint64_t FunctorSize=64>
116  class task : virtual public task_base, virtual public promise<R> {
117  public:
118  typedef std::shared_ptr<task<R,FunctorSize>> ptr;
119 
120  virtual ~task(){}
121 
122  template<typename Functor>
123  static ptr create( Functor&& f, const char* desc )
124  {
125  return ptr( new task<R,FunctorSize>( std::move(f), desc ) );
126  }
127  virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
128  private:
129  template<typename Functor>
130  task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise<R>(desc) {
131  typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
132  static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
133  new ((char*)&_functor) FunctorType( std::forward<Functor>(f) );
135 
136  _promise_impl = static_cast<promise<R>*>(this);
138  }
139 
140  alignas(double) char _functor[FunctorSize];
141  };
142 
143  template<uint64_t FunctorSize>
144  class task<void,FunctorSize> : public task_base, public promise<void> {
145  public:
146  typedef std::shared_ptr<task<void,FunctorSize>> ptr;
147 
148  virtual ~task(){}
149 
150  template<typename Functor>
151  static ptr create( Functor&& f, const char* desc )
152  {
153  return ptr( new task<void,FunctorSize>( std::move(f), desc ) );
154  }
155  virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
156  private:
157  template<typename Functor>
158  task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise<void>(desc) {
159  typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
160  static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
161  new ((char*)&_functor) FunctorType( std::forward<Functor>(f) );
163 
164  _promise_impl = static_cast<promise<void>*>(this);
166  }
167 
168  alignas(double) char _functor[FunctorSize];
169  };
170 
171 }
fc::task_base::_active_context
context * _active_context
Definition: task.hpp:64
fc::promise
Definition: future.hpp:109
fc::task_base::_posted_num
uint64_t _posted_num
Task priority looks like unsupported feature.
Definition: task.hpp:60
fc::task< void, FunctorSize >::cancel
virtual void cancel(const char *reason FC_CANCELATION_REASON_DEFAULT_ARG) override
Definition: task.hpp:155
fc::detail::get_task_specific_data
void * get_task_specific_data(unsigned slot)
Definition: thread_specific.cpp:41
fc::detail::specific_data_info::cleanup
void(* cleanup)(void *)
Definition: task.hpp:18
fc::task::ptr
std::shared_ptr< task< R, FunctorSize > > ptr
Definition: task.hpp:118
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::detail::specific_data_info::value
void * value
Definition: task.hpp:17
fwd.hpp
fc::task_base::_functor
void * _functor
Definition: task.hpp:83
fc
Definition: api.hpp:15
fc::thread_d
Definition: thread_d.hpp:30
fc::task< void, FunctorSize >
Definition: task.hpp:144
fc::task_base::_prio
priority _prio
Definition: task.hpp:61
fc::task_base::run_impl
void run_impl()
Definition: task.cpp:41
fc::task< void, FunctorSize >::create
static ptr create(Functor &&f, const char *desc)
Definition: task.hpp:151
FC_CANCELATION_REASON_DEFAULT_ARG
#define FC_CANCELATION_REASON_DEFAULT_ARG
Definition: future.hpp:21
fc::task::cancel
virtual void cancel(const char *reason FC_CANCELATION_REASON_DEFAULT_ARG) override
Definition: task.hpp:127
fc::task_base::_when
time_point _when
Definition: task.hpp:62
fc::task_base::~task_base
virtual ~task_base()
Definition: task.cpp:82
fc::task_base::cancel
virtual void cancel(const char *reason FC_CANCELATION_REASON_DEFAULT_ARG) override
Definition: task.cpp:64
fc::task_base::cleanup_task_specific_data
void cleanup_task_specific_data()
Definition: task.cpp:93
fc::task_base::_next
task_base * _next
Definition: task.hpp:65
fc::context
Definition: context.hpp:47
fc::detail::specific_data_info
Definition: task.hpp:15
fc::thread
Definition: thread.hpp:39
fc::detail::functor_run
Definition: task.hpp:101
fc::task_base::_set_active_context
void _set_active_context(context *)
Definition: task.cpp:87
fc::task_base
Definition: task.hpp:33
fc::task::~task
virtual ~task()
Definition: task.hpp:120
fc::task_base::_spinlock
fwd< spin_lock, 8 > _spinlock
Definition: task.hpp:79
fc::task::create
static ptr create(Functor &&f, const char *desc)
Definition: task.hpp:123
fc::detail::idle_guard
Definition: thread_d.hpp:21
priority.hpp
fc::task< void, FunctorSize >::~task
virtual ~task()
Definition: task.hpp:148
fc::task_base::_destroy_functor
void(* _destroy_functor)(void *)
Definition: task.hpp:84
fc::task_base::retain
void retain()
Definition: task.cpp:105
fc::priority
Definition: priority.hpp:9
fc::task_base::run
void run()
Definition: task.cpp:29
fc::detail::specific_data_info::specific_data_info
specific_data_info()
Definition: task.hpp:19
future.hpp
fc::detail::void_functor_run::run
static void run(void *functor, void *prom)
Definition: task.hpp:108
fc::time_point
Definition: time.hpp:44
fc::promise_base
Definition: future.hpp:61
fc::promise< void >
Definition: future.hpp:159
fc::promise_base::ptr
std::shared_ptr< promise_base > ptr
Definition: future.hpp:63
fc::task
Definition: task.hpp:116
fc::detail::specific_data_info::specific_data_info
specific_data_info(void *value, void(*cleanup)(void *))
Definition: task.hpp:23
fc::task< void, FunctorSize >::ptr
std::shared_ptr< task< void, FunctorSize > > ptr
Definition: task.hpp:146
fc::task_base::release
void release()
Definition: task.cpp:109
fc::detail::functor_destructor
Definition: task.hpp:97
fc::detail::functor_destructor::destroy
static void destroy(void *v)
Definition: task.hpp:98
fc::detail::void_functor_run
Definition: task.hpp:107
fc::task_base::task_base
task_base(void *func)
Definition: task.cpp:17
fc::task_base::_run_functor
void(* _run_functor)(void *, void *)
Definition: task.hpp:85
fc::detail::functor_run::run
static void run(void *functor, void *prom)
Definition: task.hpp:102
fc::task_base::_promise_impl
void * _promise_impl
Definition: task.hpp:82
fc::task_base::_task_specific_data
std::vector< detail::specific_data_info > * _task_specific_data
Definition: task.hpp:68
fc::fwd
Used to forward declare value types.
Definition: fwd.hpp:10