inline_executor.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright (C) 2014 Vicente J. Botet Escriba
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. // 2013/11 Vicente J. Botet Escriba
  7. // first implementation of a simple serial scheduler.
  8. #ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP
  9. #define BOOST_THREAD_INLINE_EXECUTOR_HPP
  10. #include <boost/thread/detail/config.hpp>
  11. #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
  12. #include <exception> // std::terminate
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/thread/detail/delete.hpp>
  15. #include <boost/thread/detail/move.hpp>
  16. #include <boost/thread/executors/work.hpp>
  17. #include <boost/thread/mutex.hpp>
  18. #include <boost/thread/lock_guard.hpp>
  19. #include <boost/thread/concurrent_queues/queue_op_status.hpp> // sync_queue_is_closed
  20. #include <boost/config/abi_prefix.hpp>
  21. namespace boost
  22. {
  23. namespace executors
  24. {
  25. class inline_executor
  26. {
  27. public:
  28. /// type-erasure to store the works to do
  29. typedef executors::work work;
  30. bool closed_;
  31. mutable mutex mtx_;
  32. /**
  33. * Effects: try to execute one task.
  34. * Returns: whether a task has been executed.
  35. * Throws: whatever the current task constructor throws or the task() throws.
  36. */
  37. bool try_executing_one()
  38. {
  39. return false;
  40. }
  41. public:
  42. /// inline_executor is not copyable.
  43. BOOST_THREAD_NO_COPYABLE(inline_executor)
  44. /**
  45. * \b Effects: creates a inline executor that runs closures immediately.
  46. *
  47. * \b Throws: Nothing.
  48. */
  49. inline_executor()
  50. : closed_(false)
  51. {
  52. }
  53. /**
  54. * \b Effects: Destroys the inline executor.
  55. *
  56. * \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor.
  57. */
  58. ~inline_executor()
  59. {
  60. // signal to all the worker thread that there will be no more submissions.
  61. close();
  62. }
  63. /**
  64. * \b Effects: close the \c inline_executor for submissions.
  65. * The loop will work until there is no more closures to run.
  66. */
  67. void close()
  68. {
  69. lock_guard<mutex> lk(mtx_);
  70. closed_ = true;
  71. }
  72. /**
  73. * \b Returns: whether the pool is closed for submissions.
  74. */
  75. bool closed(lock_guard<mutex>& )
  76. {
  77. return closed_;
  78. }
  79. bool closed()
  80. {
  81. lock_guard<mutex> lk(mtx_);
  82. return closed(lk);
  83. }
  84. /**
  85. * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
  86. *
  87. * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
  88. * If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads.
  89. *
  90. * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
  91. *
  92. * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
  93. * Whatever exception that can be throw while storing the closure.
  94. */
  95. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  96. template <typename Closure>
  97. void submit(Closure & closure)
  98. {
  99. {
  100. lock_guard<mutex> lk(mtx_);
  101. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  102. }
  103. try
  104. {
  105. closure();
  106. }
  107. catch (...)
  108. {
  109. std::terminate();
  110. return;
  111. }
  112. }
  113. #endif
  114. void submit(void (*closure)())
  115. {
  116. {
  117. lock_guard<mutex> lk(mtx_);
  118. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  119. }
  120. try
  121. {
  122. closure();
  123. }
  124. catch (...)
  125. {
  126. std::terminate();
  127. return;
  128. }
  129. }
  130. template <typename Closure>
  131. void submit(BOOST_THREAD_FWD_REF(Closure) closure)
  132. {
  133. {
  134. lock_guard<mutex> lk(mtx_);
  135. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  136. }
  137. try
  138. {
  139. closure();
  140. }
  141. catch (...)
  142. {
  143. std::terminate();
  144. return;
  145. }
  146. }
  147. /**
  148. * \b Requires: This must be called from an scheduled task.
  149. *
  150. * \b Effects: reschedule functions until pred()
  151. */
  152. template <typename Pred>
  153. bool reschedule_until(Pred const& )
  154. {
  155. return false;
  156. }
  157. };
  158. }
  159. using executors::inline_executor;
  160. }
  161. #include <boost/config/abi_suffix.hpp>
  162. #endif
  163. #endif