thread_executor.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. // 2014/01 Vicente J. Botet Escriba
  7. // first implementation of a thread_executor.
  8. #ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP
  9. #define BOOST_THREAD_THREAD_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 <boost/throw_exception.hpp>
  13. #include <boost/thread/detail/delete.hpp>
  14. #include <boost/thread/detail/move.hpp>
  15. #include <boost/thread/executors/work.hpp>
  16. #include <boost/thread/executors/executor.hpp>
  17. #include <boost/thread/mutex.hpp>
  18. #include <boost/thread/lock_guard.hpp>
  19. #include <boost/thread/thread_only.hpp>
  20. #include <boost/thread/scoped_thread.hpp>
  21. #include <boost/thread/csbl/vector.hpp>
  22. #include <boost/thread/concurrent_queues/queue_op_status.hpp>
  23. #include <boost/config/abi_prefix.hpp>
  24. namespace boost
  25. {
  26. namespace executors
  27. {
  28. class thread_executor
  29. {
  30. public:
  31. /// type-erasure to store the works to do
  32. typedef executors::work work;
  33. bool closed_;
  34. typedef scoped_thread<> thread_t;
  35. typedef csbl::vector<thread_t> threads_type;
  36. threads_type threads_;
  37. mutable mutex mtx_;
  38. /**
  39. * Effects: try to execute one task.
  40. * Returns: whether a task has been executed.
  41. * Throws: whatever the current task constructor throws or the task() throws.
  42. */
  43. bool try_executing_one()
  44. {
  45. return false;
  46. }
  47. public:
  48. /// thread_executor is not copyable.
  49. BOOST_THREAD_NO_COPYABLE(thread_executor)
  50. /**
  51. * \b Effects: creates a inline executor that runs closures immediately.
  52. *
  53. * \b Throws: Nothing.
  54. */
  55. thread_executor()
  56. : closed_(false)
  57. {
  58. }
  59. /**
  60. * \b Effects: Waits for closures (if any) to complete, then joins and destroys the threads.
  61. *
  62. * \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor.
  63. */
  64. ~thread_executor()
  65. {
  66. // signal to all the worker thread that there will be no more submissions.
  67. close();
  68. // all the scoped threads will join before destroying
  69. }
  70. /**
  71. * \b Effects: close the \c thread_executor for submissions.
  72. * The loop will work until there is no more closures to run.
  73. */
  74. void close()
  75. {
  76. lock_guard<mutex> lk(mtx_);
  77. closed_ = true;
  78. }
  79. /**
  80. * \b Returns: whether the pool is closed for submissions.
  81. */
  82. bool closed(lock_guard<mutex>& )
  83. {
  84. return closed_;
  85. }
  86. bool closed()
  87. {
  88. lock_guard<mutex> lk(mtx_);
  89. return closed(lk);
  90. }
  91. /**
  92. * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
  93. *
  94. * \b Effects: The specified \c closure will be scheduled for execution at some point in the future.
  95. * If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads.
  96. *
  97. * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables.
  98. *
  99. * \b Throws: \c sync_queue_is_closed if the thread pool is closed.
  100. * Whatever exception that can be throw while storing the closure.
  101. */
  102. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  103. template <typename Closure>
  104. void submit(Closure & closure)
  105. {
  106. lock_guard<mutex> lk(mtx_);
  107. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  108. threads_.reserve(threads_.size() + 1);
  109. thread th(closure);
  110. threads_.push_back(thread_t(boost::move(th)));
  111. }
  112. #endif
  113. void submit(void (*closure)())
  114. {
  115. lock_guard<mutex> lk(mtx_);
  116. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  117. threads_.reserve(threads_.size() + 1);
  118. thread th(closure);
  119. threads_.push_back(thread_t(boost::move(th)));
  120. }
  121. template <typename Closure>
  122. void submit(BOOST_THREAD_FWD_REF(Closure) closure)
  123. {
  124. lock_guard<mutex> lk(mtx_);
  125. if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
  126. threads_.reserve(threads_.size() + 1);
  127. thread th(boost::forward<Closure>(closure));
  128. threads_.push_back(thread_t(boost::move(th)));
  129. }
  130. /**
  131. * \b Requires: This must be called from an scheduled task.
  132. *
  133. * \b Effects: reschedule functions until pred()
  134. */
  135. template <typename Pred>
  136. bool reschedule_until(Pred const&)
  137. {
  138. return false;
  139. }
  140. };
  141. }
  142. using executors::thread_executor;
  143. }
  144. #include <boost/config/abi_suffix.hpp>
  145. #endif
  146. #endif