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