1 //  Copyright (c) 2007-2017 Hartmut Kaiser
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 /// \file hpx/runtime/launch_policy.hpp
7 
8 #if !defined(HPX_RUNTIME_LAUNCH_POLICY_AUG_13_2015_0647PM)
9 #define HPX_RUNTIME_LAUNCH_POLICY_AUG_13_2015_0647PM
10 
11 #include <hpx/config.hpp>
12 #include <hpx/runtime/threads/thread_enums.hpp>
13 #include <hpx/runtime/serialization/serialization_fwd.hpp>
14 
15 #include <type_traits>
16 #include <utility>
17 
18 namespace hpx
19 {
20     /// \cond NOINTERNAL
21     namespace detail
22     {
23         enum class launch_policy
24         {
25             async = 0x01,
26             deferred = 0x02,
27             task = 0x04,  // see N3632
28             sync = 0x08,
29             fork = 0x10,  // same as async, but forces continuation stealing
30             apply = 0x20,
31 
32             sync_policies = 0x0a,       // sync | deferred
33             async_policies = 0x15,      // async | task | fork
34             all = 0x3f                  // async | deferred | task | sync |
35                                         // fork | apply
36         };
37 
38         struct policy_holder_base
39         {
policy_holder_basehpx::detail::policy_holder_base40             HPX_CONSTEXPR explicit policy_holder_base(launch_policy p,
41                     threads::thread_priority priority =
42                         threads::thread_priority_default) noexcept
43               : policy_(p),
44                 priority_(priority)
45             {}
46 
operator boolhpx::detail::policy_holder_base47             HPX_CONSTEXPR explicit operator bool() const noexcept
48             {
49                 return is_valid();
50             }
51 
get_policyhpx::detail::policy_holder_base52             HPX_CONSTEXPR launch_policy get_policy() const noexcept
53             {
54                 return policy_;
55             }
56 
is_validhpx::detail::policy_holder_base57             HPX_CONSTEXPR bool is_valid() const noexcept
58             {
59                 return static_cast<int>(policy_) != 0;
60             }
61 
get_priorityhpx::detail::policy_holder_base62             HPX_CONSTEXPR threads::thread_priority get_priority() const
63             {
64                 return priority_;
65             }
66 
67             launch_policy policy_;
68             threads::thread_priority priority_;
69 
70         private:
71             friend class serialization::access;
72 
73             HPX_EXPORT void load(serialization::input_archive& ar, unsigned);
74             HPX_EXPORT void save(serialization::output_archive& ar, unsigned) const;
75 
76             HPX_SERIALIZATION_SPLIT_MEMBER()
77         };
78 
79         ///////////////////////////////////////////////////////////////////////
80         template <typename Derived = void>
81         struct policy_holder : policy_holder_base
82         {
policy_holderhpx::detail::policy_holder83             HPX_CONSTEXPR explicit policy_holder(launch_policy p,
84                     threads::thread_priority priority =
85                         threads::thread_priority_default) noexcept
86               : policy_holder_base(p, priority)
87             {}
88 
policy_holderhpx::detail::policy_holder89             HPX_CONSTEXPR explicit policy_holder(policy_holder_base p) noexcept
90               : policy_holder_base(p)
91             {}
92 
operator launch_policyhpx::detail::policy_holder93             HPX_CONSTEXPR operator launch_policy() const noexcept
94             {
95                 return static_cast<Derived const*>(this)->get_policy();
96             }
97 
operator boolhpx::detail::policy_holder98             HPX_CONSTEXPR explicit operator bool() const noexcept
99             {
100                 return static_cast<Derived const*>(this)->is_valid();
101             }
102 
policyhpx::detail::policy_holder103             HPX_CONSTEXPR launch_policy policy() const
104             {
105                 return static_cast<Derived const*>(this)->get_policy();
106             }
priorityhpx::detail::policy_holder107             HPX_CONSTEXPR threads::thread_priority priority() const
108             {
109                 return static_cast<Derived const*>(this)->get_priority();
110             }
111         };
112 
113         template <>
114         struct policy_holder<void> : policy_holder_base
115         {
policy_holderhpx::detail::policy_holder116             HPX_CONSTEXPR explicit policy_holder(launch_policy p,
117                     threads::thread_priority priority =
118                         threads::thread_priority_default) noexcept
119               : policy_holder_base(p, priority)
120             {}
121 
policy_holderhpx::detail::policy_holder122             HPX_CONSTEXPR explicit policy_holder(policy_holder_base p) noexcept
123               : policy_holder_base(p)
124             {}
125 
operator launch_policyhpx::detail::policy_holder126             HPX_CONSTEXPR operator launch_policy() const noexcept
127             {
128                 return this->policy_holder_base::get_policy();
129             }
130 
operator boolhpx::detail::policy_holder131             HPX_CONSTEXPR explicit operator bool() const noexcept
132             {
133                 return this->policy_holder_base::is_valid();
134             }
135 
policyhpx::detail::policy_holder136             HPX_CONSTEXPR launch_policy policy() const
137             {
138                 return this->policy_holder_base::get_policy();
139             }
priorityhpx::detail::policy_holder140             HPX_CONSTEXPR threads::thread_priority priority() const
141             {
142                 return this->policy_holder_base::get_priority();
143             }
144         };
145 
146         ///////////////////////////////////////////////////////////////////////
147         struct async_policy : policy_holder<async_policy>
148         {
async_policyhpx::detail::async_policy149             HPX_CONSTEXPR explicit async_policy(
150                     threads::thread_priority priority =
151                         threads::thread_priority_default) noexcept
152               : policy_holder<async_policy>(launch_policy::async, priority)
153             {}
154 
operator ()hpx::detail::async_policy155             HPX_CONSTEXPR async_policy operator()(
156                 threads::thread_priority priority) const noexcept
157             {
158                 return async_policy(priority);
159             }
160         };
161 
162         struct fork_policy : policy_holder<fork_policy>
163         {
fork_policyhpx::detail::fork_policy164             HPX_CONSTEXPR explicit fork_policy(
165                     threads::thread_priority priority =
166                         threads::thread_priority_boost) noexcept
167               : policy_holder<fork_policy>(launch_policy::fork, priority)
168             {}
169 
operator ()hpx::detail::fork_policy170             HPX_CONSTEXPR fork_policy operator()(
171                 threads::thread_priority priority) const noexcept
172             {
173                 return fork_policy(priority);
174             }
175         };
176 
177         struct sync_policy : policy_holder<sync_policy>
178         {
sync_policyhpx::detail::sync_policy179             HPX_CONSTEXPR sync_policy() noexcept
180               : policy_holder<sync_policy>(launch_policy::sync)
181             {}
182         };
183 
184         struct deferred_policy : policy_holder<deferred_policy>
185         {
deferred_policyhpx::detail::deferred_policy186             HPX_CONSTEXPR deferred_policy() noexcept
187               : policy_holder<deferred_policy>(launch_policy::deferred)
188             {}
189         };
190 
191         struct apply_policy : policy_holder<apply_policy>
192         {
apply_policyhpx::detail::apply_policy193             HPX_CONSTEXPR apply_policy() noexcept
194               : policy_holder<apply_policy>(launch_policy::apply)
195             {}
196         };
197 
198         template <typename Pred>
199         struct select_policy : policy_holder<select_policy<Pred> >
200         {
201             template <typename F, typename U =
202                 typename std::enable_if<!std::is_same<
203                     select_policy<Pred>, typename std::decay<F>::type
204                 >::value>::type>
select_policyhpx::detail::select_policy205             explicit select_policy(F && f, threads::thread_priority priority =
206                         threads::thread_priority_default)
207               : policy_holder<select_policy<Pred> >(launch_policy::async, priority)
208               , pred_(std::forward<F>(f))
209             {}
210 
get_policyhpx::detail::select_policy211             HPX_CONSTEXPR launch_policy get_policy() const
212             {
213                 return pred_();
214             }
215 
is_validhpx::detail::select_policy216             HPX_CONSTEXPR bool is_valid() const noexcept
217             {
218                 return true;
219             }
220 
221         private:
222             Pred pred_;
223         };
224 
225         struct select_policy_generator
226         {
operator ()hpx::detail::select_policy_generator227             HPX_CONSTEXPR async_policy operator()(
228                 threads::thread_priority priority) const noexcept
229             {
230                 return async_policy(priority);
231             }
232 
233             template <typename F>
operator ()hpx::detail::select_policy_generator234             select_policy<typename std::decay<F>::type> operator()(F && f,
235                 threads::thread_priority priority =
236                     threads::thread_priority_default) const
237             {
238                 return select_policy<typename std::decay<F>::type>(
239                     std::forward<F>(f), priority);
240             }
241         };
242 
243         ///////////////////////////////////////////////////////////////////////
244         template <typename Left, typename Right>
operator &(policy_holder<Left> const & lhs,policy_holder<Right> const & rhs)245         HPX_CONSTEXPR inline policy_holder_base operator&(
246             policy_holder<Left> const& lhs,
247             policy_holder<Right> const& rhs) noexcept
248         {
249             return policy_holder_base(
250                 static_cast<launch_policy>(
251                     static_cast<int>(lhs.policy()) &
252                         static_cast<int>(rhs.policy())
253                 ));
254         }
255 
256         template <typename Left, typename Right>
operator |(policy_holder<Left> const & lhs,policy_holder<Right> const & rhs)257         HPX_CONSTEXPR inline policy_holder_base operator|(
258             policy_holder<Left> const& lhs,
259             policy_holder<Right> const& rhs) noexcept
260         {
261             return policy_holder_base(
262                 static_cast<launch_policy>(
263                     static_cast<int>(lhs.policy()) |
264                         static_cast<int>(rhs.policy())
265                 ));
266         }
267 
268         template <typename Left, typename Right>
operator ^(policy_holder<Left> const & lhs,policy_holder<Right> const & rhs)269         HPX_CONSTEXPR inline policy_holder_base operator^(
270             policy_holder<Left> const& lhs,
271             policy_holder<Right> const& rhs) noexcept
272         {
273             return policy_holder_base(
274                 static_cast<launch_policy>(
275                     static_cast<int>(lhs.policy()) ^
276                         static_cast<int>(rhs.policy())
277                 ));
278         }
279 
280         template <typename Derived>
281         HPX_CONSTEXPR inline policy_holder<Derived>
operator ~(policy_holder<Derived> const & p)282         operator~(policy_holder<Derived> const& p) noexcept
283         {
284             return policy_holder<Derived>(
285                 static_cast<launch_policy>(
286                     ~static_cast<int>(p.policy())
287                 ));
288         }
289 
290         template <typename Left, typename Right>
operator &=(policy_holder<Left> & lhs,policy_holder<Right> const & rhs)291         inline policy_holder<Left> operator&=(
292             policy_holder<Left>& lhs, policy_holder<Right> const& rhs) noexcept
293         {
294             lhs = policy_holder<Left>(lhs & rhs);
295             return lhs;
296         }
297 
298         template <typename Left, typename Right>
operator |=(policy_holder<Left> & lhs,policy_holder<Right> const & rhs)299         inline policy_holder<Left> operator|=(
300             policy_holder<Left>& lhs, policy_holder<Right> const& rhs) noexcept
301         {
302             lhs = policy_holder<Left>(lhs | rhs);
303             return lhs;
304         }
305 
306         template <typename Left, typename Right>
operator ^=(policy_holder<Left> & lhs,policy_holder<Right> const & rhs)307         inline policy_holder<Left> operator^=(
308             policy_holder<Left>& lhs, policy_holder<Right> const& rhs) noexcept
309         {
310             lhs = policy_holder<Left>(lhs ^ rhs);
311             return lhs;
312         }
313 
314         template <typename Left, typename Right>
operator ==(policy_holder<Left> const & lhs,policy_holder<Right> const & rhs)315         HPX_CONSTEXPR inline bool operator==(policy_holder<Left> const& lhs,
316             policy_holder<Right> const& rhs) noexcept
317         {
318             return static_cast<int>(lhs.policy()) == static_cast<int>(rhs.policy());
319         }
320 
321         template <typename Left, typename Right>
operator !=(policy_holder<Left> const & lhs,policy_holder<Right> const & rhs)322         HPX_CONSTEXPR inline bool operator!=(policy_holder<Left> const& lhs,
323             policy_holder<Right> const& rhs) noexcept
324         {
325             return !(lhs == rhs);
326         }
327     }
328     /// \endcond
329 
330     ///////////////////////////////////////////////////////////////////////////
331     /// Launch policies for \a hpx::async etc.
332     struct launch : detail::policy_holder<>
333     {
334         ///////////////////////////////////////////////////////////////////////
335         /// Default constructor. This creates a launch policy representing all
336         /// possible launch modes
launchhpx::launch337         HPX_CONSTEXPR launch() noexcept
338           : detail::policy_holder<>{detail::launch_policy::all}
339         {}
340 
341         /// \cond NOINTERNAL
342         template <typename Derived>
launchhpx::launch343         HPX_CONSTEXPR launch(detail::policy_holder<Derived> const& ph) noexcept
344           : detail::policy_holder<>{ph}
345         {}
346 
launchhpx::launch347         HPX_CONSTEXPR launch(detail::policy_holder_base const& ph) noexcept
348           : detail::policy_holder<>{ph}
349         {}
350         /// \endcond
351 
352         /// Create a launch policy representing asynchronous execution
launchhpx::launch353         HPX_CONSTEXPR launch(detail::async_policy) noexcept
354           : detail::policy_holder<>{detail::launch_policy::async}
355         {}
356 
357         /// Create a launch policy representing asynchronous execution. The
358         /// new thread is executed in a preferred way
launchhpx::launch359         HPX_CONSTEXPR launch(detail::fork_policy) noexcept
360           : detail::policy_holder<>{detail::launch_policy::fork}
361         {}
362 
363         /// Create a launch policy representing synchronous execution
launchhpx::launch364         HPX_CONSTEXPR launch(detail::sync_policy) noexcept
365           : detail::policy_holder<>{detail::launch_policy::sync}
366         {}
367 
368         /// Create a launch policy representing deferred execution
launchhpx::launch369         HPX_CONSTEXPR launch(detail::deferred_policy) noexcept
370           : detail::policy_holder<>{detail::launch_policy::deferred}
371         {}
372 
373         /// Create a launch policy representing fire and forget execution
launchhpx::launch374         HPX_CONSTEXPR launch(detail::apply_policy) noexcept
375           : detail::policy_holder<>{detail::launch_policy::apply}
376         {}
377 
378         /// Create a launch policy representing fire and forget execution
379         template <typename F>
launchhpx::launch380         HPX_CONSTEXPR launch(detail::select_policy<F> const& p) noexcept
381           : detail::policy_holder<>{p.policy()}
382         {}
383 
384         ///////////////////////////////////////////////////////////////////////
385         /// \cond NOINTERNAL
386         using async_policy = detail::async_policy;
387         using fork_policy = detail::fork_policy;
388         using sync_policy = detail::sync_policy;
389         using deferred_policy = detail::deferred_policy;
390         using apply_policy = detail::apply_policy;
391         template <typename F>
392         using select_policy = detail::select_policy<F>;
393         /// \endcond
394 
395         ///////////////////////////////////////////////////////////////////////
396         /// Predefined launch policy representing asynchronous execution
397         HPX_EXPORT static const detail::async_policy async;
398 
399         /// Predefined launch policy representing asynchronous execution.The
400         /// new thread is executed in a preferred way
401         HPX_EXPORT static const detail::fork_policy fork;
402 
403         /// Predefined launch policy representing synchronous execution
404         HPX_EXPORT static const detail::sync_policy sync;
405 
406         /// Predefined launch policy representing deferred execution
407         HPX_EXPORT static const detail::deferred_policy deferred;
408 
409         /// Predefined launch policy representing fire and forget execution
410         HPX_EXPORT static const detail::apply_policy apply;
411 
412         /// Predefined launch policy representing delayed policy selection
413         HPX_EXPORT static const detail::select_policy_generator select;
414 
415         /// \cond NOINTERNAL
416         HPX_EXPORT static const detail::policy_holder<> all;
417         HPX_EXPORT static const detail::policy_holder<> sync_policies;
418         HPX_EXPORT static const detail::policy_holder<> async_policies;
419         /// \endcond
420     };
421 
422     ///////////////////////////////////////////////////////////////////////////
423     /// \cond NOINTERNAL
424     namespace detail
425     {
426         HPX_FORCEINLINE HPX_CONSTEXPR
has_async_policy(launch p)427         bool has_async_policy(launch p) noexcept
428         {
429             return bool(
430                 static_cast<int>(p.get_policy()) &
431                     static_cast<int>(detail::launch_policy::async_policies)
432             );
433         }
434 
435         template <typename F>
436         HPX_FORCEINLINE HPX_CONSTEXPR
has_async_policy(detail::policy_holder<F> const & p)437         bool has_async_policy(detail::policy_holder<F> const& p) noexcept
438         {
439             return bool(
440                 static_cast<int>(p.policy()) &
441                     static_cast<int>(detail::launch_policy::async_policies)
442             );
443         }
444     }
445     /// \endcond
446 }
447 
448 #endif
449