thread_executor.hpp 4.5 KB

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