semaphore.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
  11. #define BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP
  12. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include <boost/interprocess/detail/config_begin.hpp>
  16. #include <boost/interprocess/detail/workaround.hpp>
  17. #include <boost/interprocess/detail/atomic.hpp>
  18. #include <boost/interprocess/detail/os_thread_functions.hpp>
  19. #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
  20. #include <boost/interprocess/sync/spin/wait.hpp>
  21. #include <boost/cstdint.hpp>
  22. namespace boost {
  23. namespace interprocess {
  24. namespace ipcdetail {
  25. class spin_semaphore
  26. {
  27. spin_semaphore(const spin_semaphore &);
  28. spin_semaphore &operator=(const spin_semaphore &);
  29. public:
  30. spin_semaphore(unsigned int initialCount);
  31. ~spin_semaphore();
  32. void post();
  33. void wait();
  34. bool try_wait();
  35. bool timed_wait(const boost::posix_time::ptime &abs_time);
  36. // int get_count() const;
  37. private:
  38. volatile boost::uint32_t m_count;
  39. };
  40. inline spin_semaphore::~spin_semaphore()
  41. {}
  42. inline spin_semaphore::spin_semaphore(unsigned int initialCount)
  43. { ipcdetail::atomic_write32(&this->m_count, boost::uint32_t(initialCount)); }
  44. inline void spin_semaphore::post()
  45. {
  46. ipcdetail::atomic_inc32(&m_count);
  47. }
  48. inline void spin_semaphore::wait()
  49. {
  50. spin_wait swait;
  51. while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){
  52. swait.yield();
  53. }
  54. }
  55. inline bool spin_semaphore::try_wait()
  56. {
  57. return ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0));
  58. }
  59. inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
  60. {
  61. if(abs_time == boost::posix_time::pos_infin){
  62. this->wait();
  63. return true;
  64. }
  65. //Obtain current count and target time
  66. boost::posix_time::ptime now(microsec_clock::universal_time());
  67. spin_wait swait;
  68. do{
  69. if(this->try_wait()){
  70. break;
  71. }
  72. now = microsec_clock::universal_time();
  73. if(now >= abs_time){
  74. return this->try_wait();
  75. }
  76. // relinquish current time slice
  77. swait.yield();
  78. }while (true);
  79. return true;
  80. }
  81. //inline int spin_semaphore::get_count() const
  82. //{
  83. //return (int)ipcdetail::atomic_read32(&m_count);
  84. //}
  85. } //namespace ipcdetail {
  86. } //namespace interprocess {
  87. } //namespace boost {
  88. #include <boost/interprocess/detail/config_end.hpp>
  89. #endif //BOOST_INTERPROCESS_DETAIL_SPIN_SEMAPHORE_HPP