/Src/Dependencies/Boost/boost/thread/pthread/once.hpp

http://hadesmem.googlecode.com/ · C++ Header · 95 lines · 72 code · 14 blank · 9 comment · 4 complexity · 45acd5ebda8e0b6a2a92146b2ad5f1c4 MD5 · raw file

  1. #ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
  2. #define BOOST_THREAD_PTHREAD_ONCE_HPP
  3. // once.hpp
  4. //
  5. // (C) Copyright 2007-8 Anthony Williams
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #include <boost/thread/detail/config.hpp>
  11. #include <boost/config.hpp>
  12. #include <pthread.h>
  13. #include <boost/assert.hpp>
  14. #include "pthread_mutex_scoped_lock.hpp"
  15. #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
  16. #include <boost/cstdint.hpp>
  17. #include <boost/config/abi_prefix.hpp>
  18. namespace boost
  19. {
  20. struct once_flag
  21. {
  22. boost::uintmax_t epoch;
  23. };
  24. namespace detail
  25. {
  26. BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
  27. BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
  28. BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
  29. BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
  30. }
  31. #define BOOST_ONCE_INITIAL_FLAG_VALUE 0
  32. #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
  33. // Based on Mike Burrows fast_pthread_once algorithm as described in
  34. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
  35. template<typename Function>
  36. void call_once(once_flag& flag,Function f)
  37. {
  38. static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
  39. static boost::uintmax_t const being_initialized=uninitialized_flag+1;
  40. boost::uintmax_t const epoch=flag.epoch;
  41. boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
  42. if(epoch<this_thread_epoch)
  43. {
  44. pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
  45. while(flag.epoch<=being_initialized)
  46. {
  47. if(flag.epoch==uninitialized_flag)
  48. {
  49. flag.epoch=being_initialized;
  50. #ifndef BOOST_NO_EXCEPTIONS
  51. try
  52. {
  53. #endif
  54. pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
  55. f();
  56. #ifndef BOOST_NO_EXCEPTIONS
  57. }
  58. catch(...)
  59. {
  60. flag.epoch=uninitialized_flag;
  61. BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
  62. throw;
  63. }
  64. #endif
  65. flag.epoch=--detail::once_global_epoch;
  66. BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
  67. }
  68. else
  69. {
  70. while(flag.epoch==being_initialized)
  71. {
  72. BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
  73. }
  74. }
  75. }
  76. this_thread_epoch=detail::once_global_epoch;
  77. }
  78. }
  79. }
  80. #include <boost/config/abi_suffix.hpp>
  81. #endif