1 // Copyright (c) 2007-2015 Hartmut Kaiser 2 // Copyright (c) 2018 Thomas Heller 3 // Copyright (c) 2011 Bryce Lelbach 4 // Copyright (c) 2008-2009 Chirag Dekate, Anshul Tandon 5 // 6 // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef HPX_RUNTIME_THREADS_THREAD_HELPERS_HPP 10 #define HPX_RUNTIME_THREADS_THREAD_HELPERS_HPP 11 12 #include <hpx/config.hpp> 13 #include <hpx/exception_fwd.hpp> 14 #include <hpx/runtime/naming_fwd.hpp> 15 #include <hpx/runtime/threads_fwd.hpp> 16 #include <hpx/runtime/thread_pool_helpers.hpp> 17 #include <hpx/runtime/threads/policies/scheduler_mode.hpp> 18 #include <hpx/runtime/threads/thread_data_fwd.hpp> 19 #include <hpx/runtime/threads/thread_enums.hpp> 20 #include <hpx/util_fwd.hpp> 21 #include <hpx/util/unique_function.hpp> 22 #include <hpx/util/register_locks.hpp> 23 #include <hpx/util/steady_clock.hpp> 24 #include <hpx/util/thread_description.hpp> 25 26 #include <atomic> 27 #include <chrono> 28 #include <cstddef> 29 #include <cstdint> 30 #include <type_traits> 31 #include <utility> 32 33 /////////////////////////////////////////////////////////////////////////////// 34 namespace hpx { namespace threads 35 { 36 /// \cond NOINTERNAL 37 class thread_init_data; 38 /// \endcond 39 40 /////////////////////////////////////////////////////////////////////////// 41 /// \brief Set the thread state of the \a thread referenced by the 42 /// thread_id \a id. 43 /// 44 /// \param id [in] The thread id of the thread the state should 45 /// be modified for. 46 /// \param state [in] The new state to be set for the thread 47 /// referenced by the \a id parameter. 48 /// \param stateex [in] The new extended state to be set for the 49 /// thread referenced by the \a id parameter. 50 /// \param priority 51 /// \param ec [in,out] this represents the error status on exit, 52 /// if this is pre-initialized to \a hpx#throws 53 /// the function will throw on error instead. 54 /// 55 /// \note If the thread referenced by the parameter \a id 56 /// is in \a thread_state#active state this function 57 /// schedules a new thread which will set the state of 58 /// the thread as soon as its not active anymore. The 59 /// function returns \a thread_state#active in this case. 60 /// 61 /// \returns This function returns the previous state of the 62 /// thread referenced by the \a id parameter. It will 63 /// return one of the values as defined by the 64 /// \a thread_state enumeration. If the 65 /// thread is not known to the thread-manager the 66 /// return value will be \a thread_state#unknown. 67 /// 68 /// \note As long as \a ec is not pre-initialized to 69 /// \a hpx#throws this function doesn't 70 /// throw but returns the result code using the 71 /// parameter \a ec. Otherwise it throws an instance 72 /// of hpx#exception. 73 HPX_API_EXPORT thread_state set_thread_state(thread_id_type const& id, 74 thread_state_enum state = pending, 75 thread_state_ex_enum stateex = wait_signaled, 76 thread_priority priority = thread_priority_normal, 77 hpx::error_code& ec = throws); 78 79 /////////////////////////////////////////////////////////////////////// 80 /// \brief Set the thread state of the \a thread referenced by the 81 /// thread_id \a id. 82 /// 83 /// Set a timer to set the state of the given \a thread to the given 84 /// new value after it expired (at the given time) 85 /// 86 /// \param id [in] The thread id of the thread the state should 87 /// be modified for. 88 /// \param abs_time [in] Absolute point in time for the new thread to be 89 /// run 90 /// \param started [in,out] A helper variable allowing to track the 91 /// state of the timer helper thread 92 /// \param state [in] The new state to be set for the thread 93 /// referenced by the \a id parameter. 94 /// \param stateex [in] The new extended state to be set for the 95 /// thread referenced by the \a id parameter. 96 /// \param priority 97 /// \param ec [in,out] this represents the error status on exit, 98 /// if this is pre-initialized to \a hpx#throws 99 /// the function will throw on error instead. 100 /// 101 /// \returns 102 /// 103 /// \note As long as \a ec is not pre-initialized to 104 /// \a hpx#throws this function doesn't 105 /// throw but returns the result code using the 106 /// parameter \a ec. Otherwise it throws an instance 107 /// of hpx#exception. 108 HPX_API_EXPORT thread_id_type set_thread_state(thread_id_type const& id, 109 util::steady_time_point const& abs_time, 110 std::atomic<bool>* started, 111 thread_state_enum state = pending, 112 thread_state_ex_enum stateex = wait_timeout, 113 thread_priority priority = thread_priority_normal, 114 error_code& ec = throws); 115 set_thread_state(thread_id_type const & id,util::steady_time_point const & abs_time,thread_state_enum state=pending,thread_state_ex_enum stateex=wait_timeout,thread_priority priority=thread_priority_normal,error_code &=throws)116 inline thread_id_type set_thread_state(thread_id_type const& id, 117 util::steady_time_point const& abs_time, 118 thread_state_enum state = pending, 119 thread_state_ex_enum stateex = wait_timeout, 120 thread_priority priority = thread_priority_normal, 121 error_code& /*ec*/ = throws) 122 { 123 return set_thread_state(id, abs_time, nullptr, state, stateex, 124 priority, throws); 125 } 126 127 /////////////////////////////////////////////////////////////////////////// 128 /// \brief Set the thread state of the \a thread referenced by the 129 /// thread_id \a id. 130 /// 131 /// Set a timer to set the state of the given \a thread to the given 132 /// new value after it expired (after the given duration) 133 /// 134 /// \param id [in] The thread id of the thread the state should 135 /// be modified for. 136 /// \param rel_time [in] Time duration after which the new thread should 137 /// be run 138 /// \param state [in] The new state to be set for the thread 139 /// referenced by the \a id parameter. 140 /// \param stateex [in] The new extended state to be set for the 141 /// thread referenced by the \a id parameter. 142 /// \param priority 143 /// \param ec [in,out] this represents the error status on exit, 144 /// if this is pre-initialized to \a hpx#throws 145 /// the function will throw on error instead. 146 /// 147 /// \returns 148 /// 149 /// \note As long as \a ec is not pre-initialized to 150 /// \a hpx#throws this function doesn't 151 /// throw but returns the result code using the 152 /// parameter \a ec. Otherwise it throws an instance 153 /// of hpx#exception. set_thread_state(thread_id_type const & id,util::steady_duration const & rel_time,thread_state_enum state=pending,thread_state_ex_enum stateex=wait_timeout,thread_priority priority=thread_priority_normal,error_code & ec=throws)154 inline thread_id_type set_thread_state(thread_id_type const& id, 155 util::steady_duration const& rel_time, 156 thread_state_enum state = pending, 157 thread_state_ex_enum stateex = wait_timeout, 158 thread_priority priority = thread_priority_normal, 159 error_code& ec = throws) 160 { 161 return set_thread_state(id, rel_time.from_now(), state, stateex, 162 priority, ec); 163 } 164 165 /////////////////////////////////////////////////////////////////////////// 166 /// The function get_thread_description is part of the thread related API 167 /// allows to query the description of one of the threads known to the 168 /// thread-manager. 169 /// 170 /// \param id [in] The thread id of the thread being queried. 171 /// \param ec [in,out] this represents the error status on exit, 172 /// if this is pre-initialized to \a hpx#throws 173 /// the function will throw on error instead. 174 /// 175 /// \returns This function returns the description of the 176 /// thread referenced by the \a id parameter. If the 177 /// thread is not known to the thread-manager the return 178 /// value will be the string "<unknown>". 179 /// 180 /// \note As long as \a ec is not pre-initialized to 181 /// \a hpx#throws this function doesn't 182 /// throw but returns the result code using the 183 /// parameter \a ec. Otherwise it throws an instance 184 /// of hpx#exception. 185 HPX_API_EXPORT util::thread_description get_thread_description( 186 thread_id_type const& id, error_code& ec = throws); 187 HPX_API_EXPORT util::thread_description set_thread_description( 188 thread_id_type const& id, 189 util::thread_description const& desc = util::thread_description(), 190 error_code& ec = throws); 191 192 HPX_API_EXPORT util::thread_description get_thread_lco_description( 193 thread_id_type const& id, error_code& ec = throws); 194 HPX_API_EXPORT util::thread_description set_thread_lco_description( 195 thread_id_type const& id, 196 util::thread_description const& desc = util::thread_description(), 197 error_code& ec = throws); 198 199 /////////////////////////////////////////////////////////////////////////// 200 /// The function get_thread_backtrace is part of the thread related API 201 /// allows to query the currently stored thread back trace (which is 202 /// captured during thread suspension). 203 /// 204 /// \param id [in] The thread id of the thread being queried. 205 /// \param ec [in,out] this represents the error status on exit, 206 /// if this is pre-initialized to \a hpx#throws 207 /// the function will throw on error instead. 208 /// 209 /// \returns This function returns the currently captured stack 210 /// back trace of the thread referenced by the \a id 211 /// parameter. If the thread is not known to the 212 /// thread-manager the return value will be the zero. 213 /// 214 /// \note As long as \a ec is not pre-initialized to 215 /// \a hpx#throws this function doesn't 216 /// throw but returns the result code using the 217 /// parameter \a ec. Otherwise it throws an instance 218 /// of hpx#exception. 219 #ifdef HPX_HAVE_THREAD_FULLBACKTRACE_ON_SUSPENSION 220 HPX_API_EXPORT char const* get_thread_backtrace( 221 thread_id_type const& id, error_code& ec = throws); 222 HPX_API_EXPORT char const* set_thread_backtrace( 223 thread_id_type const& id, char const* bt = nullptr, 224 error_code& ec = throws); 225 #else 226 #if !defined(DOXYGEN) 227 HPX_API_EXPORT util::backtrace const* get_thread_backtrace( 228 thread_id_type const& id, error_code& ec = throws); 229 HPX_API_EXPORT util::backtrace const* set_thread_backtrace( 230 thread_id_type const& id, util::backtrace const* bt = nullptr, 231 error_code& ec = throws); 232 #endif 233 #endif 234 235 /////////////////////////////////////////////////////////////////////////// 236 /// The function get_thread_state is part of the thread related API. It 237 /// queries the state of one of the threads known to the thread-manager. 238 /// 239 /// \param id [in] The thread id of the thread the state should 240 /// be modified for. 241 /// \param ec [in,out] this represents the error status on exit, 242 /// if this is pre-initialized to \a hpx#throws 243 /// the function will throw on error instead. 244 /// 245 /// \returns This function returns the thread state of the 246 /// thread referenced by the \a id parameter. If the 247 /// thread is not known to the thread-manager the return 248 /// value will be \a terminated. 249 /// 250 /// \note As long as \a ec is not pre-initialized to 251 /// \a hpx#throws this function doesn't 252 /// throw but returns the result code using the 253 /// parameter \a ec. Otherwise it throws an instance 254 /// of hpx#exception. 255 HPX_API_EXPORT thread_state get_thread_state(thread_id_type const& id, 256 error_code& ec = throws); 257 258 /////////////////////////////////////////////////////////////////////////// 259 /// The function get_thread_phase is part of the thread related API. 260 /// It queries the phase of one of the threads known to the thread-manager. 261 /// 262 /// \param id [in] The thread id of the thread the phase should 263 /// be modified for. 264 /// \param ec [in,out] this represents the error status on exit, 265 /// if this is pre-initialized to \a hpx#throws 266 /// the function will throw on error instead. 267 /// 268 /// \returns This function returns the thread phase of the 269 /// thread referenced by the \a id parameter. If the 270 /// thread is not known to the thread-manager the return 271 /// value will be ~0. 272 /// 273 /// \note As long as \a ec is not pre-initialized to 274 /// \a hpx#throws this function doesn't 275 /// throw but returns the result code using the 276 /// parameter \a ec. Otherwise it throws an instance 277 /// of hpx#exception. 278 HPX_API_EXPORT std::size_t get_thread_phase(thread_id_type const& id, 279 error_code& ec = throws); 280 281 /////////////////////////////////////////////////////////////////////////// 282 // Return the number of the NUMA node the current thread is running on 283 HPX_API_EXPORT std::size_t get_numa_node_number(); 284 285 /////////////////////////////////////////////////////////////////////////// 286 /// Returns whether the given thread can be interrupted at this point. 287 /// 288 /// \param id [in] The thread id of the thread which should be 289 /// queried. 290 /// \param ec [in,out] this represents the error status on exit, 291 /// if this is pre-initialized to \a hpx#throws 292 /// the function will throw on error instead. 293 /// 294 /// \returns This function returns \a true if the given thread 295 /// can be interrupted at this point in time. It will 296 /// return \a false otherwise. 297 /// 298 /// \note As long as \a ec is not pre-initialized to 299 /// \a hpx#throws this function doesn't 300 /// throw but returns the result code using the 301 /// parameter \a ec. Otherwise it throws an instance 302 /// of hpx#exception. 303 HPX_API_EXPORT bool get_thread_interruption_enabled(thread_id_type const& id, 304 error_code& ec = throws); 305 306 /// Set whether the given thread can be interrupted at this point. 307 /// 308 /// \param id [in] The thread id of the thread which should 309 /// receive the new value. 310 /// \param enable [in] This value will determine the new interruption 311 /// enabled status for the given thread. 312 /// \param ec [in,out] this represents the error status on exit, 313 /// if this is pre-initialized to \a hpx#throws 314 /// the function will throw on error instead. 315 /// 316 /// \returns This function returns the previous value of 317 /// whether the given thread could have been interrupted. 318 /// 319 /// \note As long as \a ec is not pre-initialized to 320 /// \a hpx#throws this function doesn't 321 /// throw but returns the result code using the 322 /// parameter \a ec. Otherwise it throws an instance 323 /// of hpx#exception. 324 HPX_API_EXPORT bool set_thread_interruption_enabled(thread_id_type const& id, 325 bool enable, error_code& ec = throws); 326 327 /// Returns whether the given thread has been flagged for interruption. 328 /// 329 /// \param id [in] The thread id of the thread which should be 330 /// queried. 331 /// \param ec [in,out] this represents the error status on exit, 332 /// if this is pre-initialized to \a hpx#throws 333 /// the function will throw on error instead. 334 /// 335 /// \returns This function returns \a true if the given thread 336 /// was flagged for interruption. It will return 337 /// \a false otherwise. 338 /// 339 /// \note As long as \a ec is not pre-initialized to 340 /// \a hpx#throws this function doesn't 341 /// throw but returns the result code using the 342 /// parameter \a ec. Otherwise it throws an instance 343 /// of hpx#exception. 344 HPX_API_EXPORT bool get_thread_interruption_requested(thread_id_type const& id, 345 error_code& ec = throws); 346 347 /// Flag the given thread for interruption. 348 /// 349 /// \param id [in] The thread id of the thread which should be 350 /// interrupted. 351 /// \param flag [in] The flag encodes whether the thread should be 352 /// interrupted (if it is \a true), or 'uninterrupted' 353 /// (if it is \a false). 354 /// \param ec [in,out] this represents the error status on exit, 355 /// if this is pre-initialized to \a hpx#throws 356 /// the function will throw on error instead. 357 /// 358 /// \note As long as \a ec is not pre-initialized to 359 /// \a hpx#throws this function doesn't 360 /// throw but returns the result code using the 361 /// parameter \a ec. Otherwise it throws an instance 362 /// of hpx#exception. 363 HPX_API_EXPORT void interrupt_thread(thread_id_type const& id, bool flag, 364 error_code& ec = throws); 365 interrupt_thread(thread_id_type const & id,error_code & ec=throws)366 inline void interrupt_thread(thread_id_type const& id, error_code& ec = throws) 367 { 368 interrupt_thread(id, true, ec); 369 } 370 371 /////////////////////////////////////////////////////////////////////////// 372 /// Interrupt the current thread at this point if it was canceled. This 373 /// will throw a thread_interrupted exception, which will cancel the thread. 374 /// 375 /// \param id [in] The thread id of the thread which should be 376 /// interrupted. 377 /// \param ec [in,out] this represents the error status on exit, 378 /// if this is pre-initialized to \a hpx#throws 379 /// the function will throw on error instead. 380 /// 381 /// \note As long as \a ec is not pre-initialized to 382 /// \a hpx#throws this function doesn't 383 /// throw but returns the result code using the 384 /// parameter \a ec. Otherwise it throws an instance 385 /// of hpx#exception. 386 HPX_API_EXPORT void interruption_point(thread_id_type const& id, 387 error_code& ec = throws); 388 389 /////////////////////////////////////////////////////////////////////////// 390 /// Return priority of the given thread 391 /// 392 /// \param id [in] The thread id of the thread whose priority 393 /// is queried. 394 /// \param ec [in,out] this represents the error status on exit, 395 /// if this is pre-initialized to \a hpx#throws 396 /// the function will throw on error instead. 397 /// 398 /// \note As long as \a ec is not pre-initialized to 399 /// \a hpx#throws this function doesn't 400 /// throw but returns the result code using the 401 /// parameter \a ec. Otherwise it throws an instance 402 /// of hpx#exception. 403 HPX_API_EXPORT threads::thread_priority get_thread_priority( 404 thread_id_type const& id, error_code& ec = throws); 405 406 /////////////////////////////////////////////////////////////////////////// 407 /// Return stack size of the given thread 408 /// 409 /// \param id [in] The thread id of the thread whose priority 410 /// is queried. 411 /// \param ec [in,out] this represents the error status on exit, 412 /// if this is pre-initialized to \a hpx#throws 413 /// the function will throw on error instead. 414 /// 415 /// \note As long as \a ec is not pre-initialized to 416 /// \a hpx#throws this function doesn't 417 /// throw but returns the result code using the 418 /// parameter \a ec. Otherwise it throws an instance 419 /// of hpx#exception. 420 HPX_API_EXPORT std::ptrdiff_t get_stack_size( 421 thread_id_type const& id, error_code& ec = throws); 422 423 /////////////////////////////////////////////////////////////////////////// 424 /// \cond NOINTERNAL 425 HPX_API_EXPORT void run_thread_exit_callbacks(thread_id_type const& id, 426 error_code& ec = throws); 427 428 HPX_API_EXPORT bool add_thread_exit_callback(thread_id_type const& id, 429 util::function_nonser<void()> const& f, error_code& ec = throws); 430 431 HPX_API_EXPORT void free_thread_exit_callbacks(thread_id_type const& id, 432 error_code& ec = throws); 433 434 /////////////////////////////////////////////////////////////////////////// 435 HPX_API_EXPORT std::size_t get_thread_data(thread_id_type const& id, 436 error_code& ec = throws); 437 438 HPX_API_EXPORT std::size_t set_thread_data(thread_id_type const& id, 439 std::size_t data, error_code& ec = throws); 440 441 HPX_API_EXPORT std::size_t& get_continuation_recursion_count(); 442 HPX_API_EXPORT void reset_continuation_recursion_count(); 443 /// \endcond 444 445 /// Returns a reference to the executor which was used to create 446 /// the given thread. 447 /// 448 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 449 /// to an appropriate value when an error occurs. Otherwise, this 450 /// function will throw an \a hpx#exception with an error code of 451 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 452 /// If called outside of a HPX-thread, this function will throw 453 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 454 /// If this function is called while the thread-manager is not 455 /// running, it will throw an \a hpx#exception with an error code of 456 /// \a hpx#invalid_status. 457 /// 458 HPX_API_EXPORT threads::executors::current_executor 459 get_executor(thread_id_type const& id, error_code& ec = throws); 460 461 /// Returns a pointer to the pool that was used to run the current thread 462 /// 463 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 464 /// to an appropriate value when an error occurs. Otherwise, this 465 /// function will throw an \a hpx#exception with an error code of 466 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 467 /// If called outside of a HPX-thread, this function will throw 468 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 469 /// If this function is called while the thread-manager is not 470 /// running, it will throw an \a hpx#exception with an error code of 471 /// \a hpx#invalid_status. 472 HPX_EXPORT threads::thread_pool_base* 473 get_pool(thread_id_type const& id, error_code& ec = throws); 474 475 /// \cond NOINTERNAL 476 /// Reset internal (round robin) thread distribution scheme 477 HPX_API_EXPORT void reset_thread_distribution(); 478 479 /// Set the new scheduler mode 480 HPX_API_EXPORT void set_scheduler_mode(threads::policies::scheduler_mode); 481 /// \endcond 482 }} 483 484 namespace hpx { namespace this_thread 485 { 486 /////////////////////////////////////////////////////////////////////////// 487 /// The function \a suspend will return control to the thread manager 488 /// (suspends the current thread). It sets the new state of this thread 489 /// to the thread state passed as the parameter. 490 /// 491 /// \note Must be called from within a HPX-thread. 492 /// 493 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 494 /// to an appropriate value when an error occurs. Otherwise, this 495 /// function will throw an \a hpx#exception with an error code of 496 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 497 /// If called outside of a HPX-thread, this function will throw 498 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 499 /// If this function is called while the thread-manager is not 500 /// running, it will throw an \a hpx#exception with an error code of 501 /// \a hpx#invalid_status. 502 /// 503 HPX_API_EXPORT threads::thread_state_ex_enum suspend( 504 threads::thread_state_enum state, threads::thread_id_type const& id, 505 util::thread_description const& description = 506 util::thread_description("this_thread::suspend"), 507 error_code& ec = throws); 508 509 /// The function \a suspend will return control to the thread manager 510 /// (suspends the current thread). It sets the new state of this thread 511 /// to the thread state passed as the parameter. 512 /// 513 /// \note Must be called from within a HPX-thread. 514 /// 515 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 516 /// to an appropriate value when an error occurs. Otherwise, this 517 /// function will throw an \a hpx#exception with an error code of 518 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 519 /// If called outside of a HPX-thread, this function will throw 520 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 521 /// If this function is called while the thread-manager is not 522 /// running, it will throw an \a hpx#exception with an error code of 523 /// \a hpx#invalid_status. 524 /// suspend(threads::thread_state_enum state=threads::pending,util::thread_description const & description=util::thread_description ("this_thread::suspend"),error_code & ec=throws)525 inline threads::thread_state_ex_enum suspend( 526 threads::thread_state_enum state = threads::pending, 527 util::thread_description const& description = 528 util::thread_description("this_thread::suspend"), 529 error_code& ec = throws) 530 { 531 return suspend(state, threads::invalid_thread_id, description, ec); 532 } 533 534 /// The function \a suspend will return control to the thread manager 535 /// (suspends the current thread). It sets the new state of this thread 536 /// to \a suspended and schedules a wakeup for this threads at the given 537 /// time. 538 /// 539 /// \note Must be called from within a HPX-thread. 540 /// 541 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 542 /// to an appropriate value when an error occurs. Otherwise, this 543 /// function will throw an \a hpx#exception with an error code of 544 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 545 /// If called outside of a HPX-thread, this function will throw 546 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 547 /// If this function is called while the thread-manager is not 548 /// running, it will throw an \a hpx#exception with an error code of 549 /// \a hpx#invalid_status. 550 /// 551 HPX_API_EXPORT threads::thread_state_ex_enum suspend( 552 util::steady_time_point const& abs_time, 553 threads::thread_id_type const& id, 554 util::thread_description const& description = 555 util::thread_description("this_thread::suspend"), 556 error_code& ec = throws); 557 558 /// The function \a suspend will return control to the thread manager 559 /// (suspends the current thread). It sets the new state of this thread 560 /// to \a suspended and schedules a wakeup for this threads at the given 561 /// time. 562 /// 563 /// \note Must be called from within a HPX-thread. 564 /// 565 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 566 /// to an appropriate value when an error occurs. Otherwise, this 567 /// function will throw an \a hpx#exception with an error code of 568 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 569 /// If called outside of a HPX-thread, this function will throw 570 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 571 /// If this function is called while the thread-manager is not 572 /// running, it will throw an \a hpx#exception with an error code of 573 /// \a hpx#invalid_status. 574 /// suspend(util::steady_time_point const & abs_time,util::thread_description const & description=util::thread_description ("this_thread::suspend"),error_code & ec=throws)575 inline threads::thread_state_ex_enum suspend( 576 util::steady_time_point const& abs_time, 577 util::thread_description const& description = 578 util::thread_description("this_thread::suspend"), 579 error_code& ec = throws) 580 { 581 return suspend(abs_time, threads::invalid_thread_id, description, ec); 582 } 583 584 /// The function \a suspend will return control to the thread manager 585 /// (suspends the current thread). It sets the new state of this thread 586 /// to \a suspended and schedules a wakeup for this threads after the given 587 /// duration. 588 /// 589 /// \note Must be called from within a HPX-thread. 590 /// 591 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 592 /// to an appropriate value when an error occurs. Otherwise, this 593 /// function will throw an \a hpx#exception with an error code of 594 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 595 /// If called outside of a HPX-thread, this function will throw 596 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 597 /// If this function is called while the thread-manager is not 598 /// running, it will throw an \a hpx#exception with an error code of 599 /// \a hpx#invalid_status. 600 /// suspend(util::steady_duration const & rel_time,util::thread_description const & description=util::thread_description ("this_thread::suspend"),error_code & ec=throws)601 inline threads::thread_state_ex_enum suspend( 602 util::steady_duration const& rel_time, 603 util::thread_description const& description = 604 util::thread_description("this_thread::suspend"), 605 error_code& ec = throws) 606 { 607 return suspend(rel_time.from_now(), threads::invalid_thread_id, 608 description, ec); 609 } 610 611 /// The function \a suspend will return control to the thread manager 612 /// (suspends the current thread). It sets the new state of this thread 613 /// to \a suspended and schedules a wakeup for this threads after the given 614 /// duration. 615 /// 616 /// \note Must be called from within a HPX-thread. 617 /// 618 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 619 /// to an appropriate value when an error occurs. Otherwise, this 620 /// function will throw an \a hpx#exception with an error code of 621 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 622 /// If called outside of a HPX-thread, this function will throw 623 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 624 /// If this function is called while the thread-manager is not 625 /// running, it will throw an \a hpx#exception with an error code of 626 /// \a hpx#invalid_status. 627 /// suspend(util::steady_duration const & rel_time,threads::thread_id_type const & id,util::thread_description const & description=util::thread_description ("this_thread::suspend"),error_code & ec=throws)628 inline threads::thread_state_ex_enum suspend( 629 util::steady_duration const& rel_time, 630 threads::thread_id_type const& id, 631 util::thread_description const& description = 632 util::thread_description("this_thread::suspend"), 633 error_code& ec = throws) 634 { 635 return suspend(rel_time.from_now(), id, description, ec); 636 } 637 638 /// The function \a suspend will return control to the thread manager 639 /// (suspends the current thread). It sets the new state of this thread 640 /// to \a suspended and schedules a wakeup for this threads after the given 641 /// time (specified in milliseconds). 642 /// 643 /// \note Must be called from within a HPX-thread. 644 /// 645 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 646 /// to an appropriate value when an error occurs. Otherwise, this 647 /// function will throw an \a hpx#exception with an error code of 648 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 649 /// If called outside of a HPX-thread, this function will throw 650 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 651 /// If this function is called while the thread-manager is not 652 /// running, it will throw an \a hpx#exception with an error code of 653 /// \a hpx#invalid_status. 654 /// suspend(std::uint64_t ms,util::thread_description const & description=util::thread_description ("this_thread::suspend"),error_code & ec=throws)655 inline threads::thread_state_ex_enum suspend(std::uint64_t ms, 656 util::thread_description const& description = 657 util::thread_description("this_thread::suspend"), 658 error_code& ec = throws) 659 { 660 return suspend(std::chrono::milliseconds(ms), threads::invalid_thread_id, 661 description, ec); 662 } 663 664 /// Returns a reference to the executor which was used to create the current 665 /// thread. 666 /// 667 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 668 /// to an appropriate value when an error occurs. Otherwise, this 669 /// function will throw an \a hpx#exception with an error code of 670 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 671 /// If called outside of a HPX-thread, this function will throw 672 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 673 /// If this function is called while the thread-manager is not 674 /// running, it will throw an \a hpx#exception with an error code of 675 /// \a hpx#invalid_status. 676 /// 677 HPX_EXPORT threads::executors::current_executor 678 get_executor(error_code& ec = throws); 679 680 /// Returns a pointer to the pool that was used to run the current thread 681 /// 682 /// \throws If <code>&ec != &throws</code>, never throws, but will set \a ec 683 /// to an appropriate value when an error occurs. Otherwise, this 684 /// function will throw an \a hpx#exception with an error code of 685 /// \a hpx#yield_aborted if it is signaled with \a wait_aborted. 686 /// If called outside of a HPX-thread, this function will throw 687 /// an \a hpx#exception with an error code of \a hpx::null_thread_id. 688 /// If this function is called while the thread-manager is not 689 /// running, it will throw an \a hpx#exception with an error code of 690 /// \a hpx#invalid_status. 691 HPX_EXPORT threads::thread_pool_base* get_pool(error_code& ec = throws); 692 693 /// \cond NOINTERNAL 694 // returns the remaining available stack space 695 HPX_EXPORT std::ptrdiff_t get_available_stack_space(); 696 697 // returns whether the remaining stack-space is at least as large as 698 // requested 699 HPX_EXPORT bool has_sufficient_stack_space( 700 std::size_t space_needed = 8 * HPX_THREADS_STACK_OVERHEAD); 701 /// \endcond 702 }} 703 704 /// \cond NOINTERNAL 705 706 /////////////////////////////////////////////////////////////////////////////// 707 // FIXME: the API function below belong into the namespace hpx::threads 708 namespace hpx { namespace applier 709 { 710 /////////////////////////////////////////////////////////////////////////// 711 /// \brief Create a new \a thread using the given function as the work to 712 /// be executed. 713 /// 714 /// \param func [in] The function to be executed as the thread-function. 715 /// This function has to expose the minimal low level 716 /// HPX-thread interface, i.e. it takes one argument (a 717 /// \a threads#thread_state_ex_enum) and returns a 718 /// \a threads#thread_state_enum. 719 /// \param description [in] A optional string describing the newly created 720 /// thread. This is useful for debugging and logging 721 /// purposes as this string will be inserted in the logs. 722 /// \param initial_state [in] The thread state the newly created thread 723 /// should have. If this is not given it defaults to 724 /// \a threads#pending, which means that the new thread 725 /// will be scheduled to run as soon as it is created. 726 /// \param run_now [in] If this is set to `true` the thread object will 727 /// be actually immediately created. Otherwise the 728 /// thread-manager creates a work-item description, which 729 /// will result in creating a thread object later (if 730 /// no work is available any more). The default is to 731 /// immediately create the thread object. 732 /// \param priority [in] This is the priority the newly created HPX-thread 733 /// should be executed with. The default is \a 734 /// threads#thread_priority_normal. This parameter is not 735 /// guaranteed to be taken into account as it depends on 736 /// the used scheduling policy whether priorities are 737 /// supported in the first place. 738 /// \param os_thread [in] The number of the shepherd thread the newly 739 /// created HPX-thread should run on. If this is given it 740 /// will be no more than a hint in any case, mainly 741 /// because even if the HPX-thread gets scheduled on the 742 /// queue of the requested shepherd thread, it still can 743 /// be stolen by another shepherd thread. If this is not 744 /// given, the system will select a shepherd thread. 745 /// \param ec [in,out] This represents the error status on exit, 746 /// if this is pre-initialized to \a hpx#throws 747 /// the function will throw on error instead. 748 /// 749 /// \returns This function will return the internal id of the newly created 750 /// HPX-thread or threads#invalid_thread_id (if run_now is set to 751 /// `false`). 752 /// 753 /// \note The value returned by the thread function will be interpreted by 754 /// the thread manager as the new thread state the executed HPX-thread 755 /// needs to be switched to. Normally, HPX-threads will either return 756 /// \a threads#terminated (if the thread should be destroyed) or 757 /// \a threads#suspended (if the thread needs to be suspended because 758 /// it is waiting for an external event to happen). The external 759 /// event will set the state of the thread back to pending, which 760 /// will re-schedule the HPX-thread. 761 /// 762 /// \throws invalid_status if the runtime system has not been started yet. 763 /// 764 /// 765 /// \note As long as \a ec is not pre-initialized to 766 /// \a hpx#throws this function doesn't 767 /// throw but returns the result code using the 768 /// parameter \a ec. Otherwise it throws an instance 769 /// of hpx#exception. 770 HPX_API_EXPORT threads::thread_id_type register_thread_plain( 771 threads::thread_function_type && func, 772 util::thread_description const& description = util::thread_description(), 773 threads::thread_state_enum initial_state = threads::pending, 774 bool run_now = true, 775 threads::thread_priority priority = threads::thread_priority_normal, 776 threads::thread_schedule_hint = threads::thread_schedule_hint(), 777 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 778 error_code& ec = throws); 779 780 /////////////////////////////////////////////////////////////////////////// 781 /// \brief Create a new \a thread using the given data. 782 /// 783 /// \note This function is completely equivalent to the first overload 784 /// of threads#register_thread_plain above, except that part of the 785 /// parameters are passed as members of the threads#thread_init_data 786 /// object. 787 /// 788 HPX_API_EXPORT threads::thread_id_type register_thread_plain( 789 threads::thread_init_data& data, 790 threads::thread_state_enum initial_state = threads::pending, 791 bool run_now = true, error_code& ec = throws); 792 793 /////////////////////////////////////////////////////////////////////////// 794 /// \brief Create a new \a thread using the given function as the work to 795 /// be executed. 796 /// 797 /// \param func [in] The function to be executed as the thread-function. 798 /// This function has to expose the minimal low level 799 /// HPX-thread interface, i.e. it takes one argument (a 800 /// \a threads#thread_state_ex_enum). The thread will be 801 /// terminated after the function returns. 802 /// 803 /// \note All other arguments are equivalent to those of the function 804 /// \a threads#register_thread_plain 805 /// 806 namespace detail 807 { 808 template <typename F> 809 struct thread_function 810 { 811 F f; 812 operator ()hpx::applier::detail::thread_function813 inline threads::thread_result_type operator()(threads::thread_arg_type) 814 { 815 // execute the actual thread function 816 f(threads::wait_signaled); 817 818 // Verify that there are no more registered locks for this 819 // OS-thread. This will throw if there are still any locks 820 // held. 821 util::force_error_on_lock(); 822 823 return threads::thread_result_type(threads::terminated, 824 threads::invalid_thread_id); 825 } 826 }; 827 828 template <typename F> 829 struct thread_function_nullary 830 { 831 F f; 832 operator ()hpx::applier::detail::thread_function_nullary833 inline threads::thread_result_type operator()(threads::thread_arg_type) 834 { 835 // execute the actual thread function 836 f(); 837 838 // Verify that there are no more registered locks for this 839 // OS-thread. This will throw if there are still any locks 840 // held. 841 util::force_error_on_lock(); 842 843 return threads::thread_result_type(threads::terminated, 844 threads::invalid_thread_id); 845 } 846 }; 847 } 848 849 template <typename F> register_thread(F && func,util::thread_description const & description=util::thread_description (),threads::thread_state_enum initial_state=threads::pending,bool run_now=true,threads::thread_priority priority=threads::thread_priority_normal,threads::thread_schedule_hint os_thread=threads::thread_schedule_hint (),threads::thread_stacksize stacksize=threads::thread_stacksize_default,error_code & ec=throws)850 threads::thread_id_type register_thread( 851 F && func, 852 util::thread_description const& description = util::thread_description(), 853 threads::thread_state_enum initial_state = threads::pending, 854 bool run_now = true, 855 threads::thread_priority priority = threads::thread_priority_normal, 856 threads::thread_schedule_hint os_thread = threads::thread_schedule_hint(), 857 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 858 error_code& ec = throws) 859 { 860 threads::thread_function_type thread_func( 861 detail::thread_function<typename std::decay<F>::type>{ 862 std::forward<F>(func)}); 863 return register_thread_plain(std::move(thread_func), 864 description, initial_state, run_now, priority, os_thread, stacksize, 865 ec); 866 } 867 868 /////////////////////////////////////////////////////////////////////////// 869 /// \brief Create a new \a thread using the given function as the work to 870 /// be executed. 871 /// 872 /// \param func [in] The function to be executed as the thread-function. 873 /// This function has to expose the minimal low level 874 /// HPX-thread interface, i.e. it takes no arguments. The 875 /// thread will be terminated after the function returns. 876 /// 877 /// \note All other arguments are equivalent to those of the function 878 /// \a threads#register_thread_plain 879 /// 880 template <typename F> register_thread_nullary(F && func,util::thread_description const & description=util::thread_description (),threads::thread_state_enum initial_state=threads::pending,bool run_now=true,threads::thread_priority priority=threads::thread_priority_normal,threads::thread_schedule_hint os_thread=threads::thread_schedule_hint (),threads::thread_stacksize stacksize=threads::thread_stacksize_default,error_code & ec=throws)881 threads::thread_id_type register_thread_nullary( 882 F && func, 883 util::thread_description const& description = util::thread_description(), 884 threads::thread_state_enum initial_state = threads::pending, 885 bool run_now = true, 886 threads::thread_priority priority = threads::thread_priority_normal, 887 threads::thread_schedule_hint os_thread = threads::thread_schedule_hint(), 888 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 889 error_code& ec = throws) 890 { 891 threads::thread_function_type thread_func( 892 detail::thread_function_nullary<typename std::decay<F>::type>{ 893 std::forward<F>(func)}); 894 return register_thread_plain(std::move(thread_func), 895 description, initial_state, run_now, priority, os_thread, stacksize, 896 ec); 897 } 898 899 /////////////////////////////////////////////////////////////////////////// 900 /// \brief Create a new work item using the given function as the 901 /// work to be executed. This work item will be used to create a 902 /// \a threads#thread instance whenever the shepherd thread runs out 903 /// of work only. The created work descriptions will be queued 904 /// separately, causing them to be converted into actual thread 905 /// objects on a first-come-first-served basis. 906 /// 907 /// \param func [in] The function to be executed as the thread-function. 908 /// This function has to expose the minimal low level 909 /// HPX-thread interface, i.e. it takes one argument (a 910 /// \a threads#thread_state_ex_enum) and returns a 911 /// \a threads#thread_state_enum. 912 /// \param description [in] A optional string describing the newly created 913 /// thread. This is useful for debugging and logging 914 /// purposes as this string will be inserted in the logs. 915 /// \param initial_state [in] The thread state the newly created thread 916 /// should have. If this is not given it defaults to 917 /// \a threads#pending, which means that the new thread 918 /// will be scheduled to run as soon as it is created. 919 /// \param priority [in] This is the priority the newly created HPX-thread 920 /// should be executed with. The default is \a 921 /// threads#thread_priority_normal. This parameter is not 922 /// guaranteed to be taken into account as it depends on 923 /// the used scheduling policy whether priorities are 924 /// supported in the first place. 925 /// \param os_thread [in] The number of the shepherd thread the newly 926 /// created HPX-thread should run on. If this is given it 927 /// will be no more than a hint in any case, mainly 928 /// because even if the HPX-thread gets scheduled on the 929 /// queue of the requested shepherd thread, it still can 930 /// be stolen by another shepherd thread. If this is not 931 /// given, the system will select a shepherd thread. 932 /// \param ec [in,out] This represents the error status on exit, 933 /// if this is pre-initialized to \a hpx#throws 934 /// the function will throw on error instead. 935 /// 936 /// \note The value returned by the thread function will be interpreted by 937 /// the thread manager as the new thread state the executed HPX-thread 938 /// needs to be switched to. Normally, HPX-threads will either return 939 /// \a threads#terminated (if the thread should be destroyed) or 940 /// \a threads#suspended (if the thread needs to be suspended because 941 /// it is waiting for an external event to happen). The external 942 /// event will set the state of the thread back to pending, which 943 /// will re-schedule the HPX-thread. 944 /// 945 /// \throws invalid_status if the runtime system has not been started yet. 946 /// 947 HPX_API_EXPORT void register_work_plain( 948 threads::thread_function_type && func, 949 util::thread_description const& description = util::thread_description(), 950 std::uint64_t /*naming::address_type*/ lva = 0, 951 threads::thread_state_enum initial_state = threads::pending, 952 threads::thread_priority priority = threads::thread_priority_normal, 953 threads::thread_schedule_hint = threads::thread_schedule_hint(), 954 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 955 error_code& ec = throws); 956 957 /////////////////////////////////////////////////////////////////////////// 958 /// \brief Create a new work item using the given function as the 959 /// work to be executed. 960 /// 961 /// \note This function is completely equivalent to the first overload 962 /// of threads#register_work_plain above, except that part of the 963 /// parameters are passed as members of the threads#thread_init_data 964 /// object. 965 /// 966 HPX_API_EXPORT void register_work_plain( 967 threads::thread_init_data& data, 968 threads::thread_state_enum initial_state = threads::pending, 969 error_code& ec = throws); 970 971 /////////////////////////////////////////////////////////////////////////// 972 /// \brief Create a new work item using the given function as the 973 /// work to be executed. 974 /// 975 /// \param func [in] The function to be executed as the thread-function. 976 /// This function has to expose the minimal low level 977 /// HPX-thread interface, i.e. it takes one argument (a 978 /// \a threads#thread_state_ex_enum). The thread will be 979 /// terminated after the function returns. 980 /// 981 /// \note All other arguments are equivalent to those of the function 982 /// \a threads#register_work_plain 983 /// 984 template <typename F> register_work(F && func,util::thread_description const & description=util::thread_description (),threads::thread_state_enum initial_state=threads::pending,threads::thread_priority priority=threads::thread_priority_normal,threads::thread_schedule_hint os_thread=threads::thread_schedule_hint (),threads::thread_stacksize stacksize=threads::thread_stacksize_default,error_code & ec=throws)985 void register_work( 986 F && func, 987 util::thread_description const& description = util::thread_description(), 988 threads::thread_state_enum initial_state = threads::pending, 989 threads::thread_priority priority = threads::thread_priority_normal, 990 threads::thread_schedule_hint os_thread = threads::thread_schedule_hint(), 991 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 992 error_code& ec = throws) 993 { 994 threads::thread_function_type thread_func( 995 detail::thread_function<typename std::decay<F>::type>{ 996 std::forward<F>(func)}); 997 return register_work_plain(std::move(thread_func), 998 description, 0, initial_state, priority, os_thread, stacksize, 999 ec); 1000 } 1001 1002 /////////////////////////////////////////////////////////////////////////// 1003 /// \brief Create a new work item using the given function as the 1004 /// work to be executed. 1005 /// 1006 /// \param func [in] The function to be executed as the thread-function. 1007 /// This function has to expose the minimal low level 1008 /// HPX-thread interface, i.e. it takes no arguments. The 1009 /// thread will be terminated after the function returns. 1010 /// 1011 /// \note All other arguments are equivalent to those of the function 1012 /// \a threads#register_work_plain 1013 /// 1014 template <typename F> register_work_nullary(F && func,util::thread_description const & description=util::thread_description (),threads::thread_state_enum initial_state=threads::pending,threads::thread_priority priority=threads::thread_priority_normal,threads::thread_schedule_hint os_thread=threads::thread_schedule_hint (),threads::thread_stacksize stacksize=threads::thread_stacksize_default,error_code & ec=throws)1015 void register_work_nullary( 1016 F && func, 1017 util::thread_description const& description = util::thread_description(), 1018 threads::thread_state_enum initial_state = threads::pending, 1019 threads::thread_priority priority = threads::thread_priority_normal, 1020 threads::thread_schedule_hint os_thread = threads::thread_schedule_hint(), 1021 threads::thread_stacksize stacksize = threads::thread_stacksize_default, 1022 error_code& ec = throws) 1023 { 1024 threads::thread_function_type thread_func( 1025 detail::thread_function_nullary<typename std::decay<F>::type>{ 1026 std::forward<F>(func)}); 1027 return register_work_plain(std::move(thread_func), 1028 description, 0, initial_state, priority, os_thread, stacksize, 1029 ec); 1030 } 1031 }} 1032 1033 /////////////////////////////////////////////////////////////////////////////// 1034 namespace hpx { namespace threads 1035 { 1036 // Import all thread creation functions into this name space (we will 1037 // deprecate the functions in namespace applier above at some point). 1038 using applier::register_thread_plain; 1039 using applier::register_thread; 1040 using applier::register_thread_nullary; 1041 1042 using applier::register_work_plain; 1043 using applier::register_work; 1044 using applier::register_work_nullary; 1045 }} 1046 1047 /// \endcond 1048 1049 #endif /*HPX_RUNTIME_THREADS_THREAD_HELPERS_HPP*/ 1050