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