Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/interprocess for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
|
Chris@16
|
12 #define BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/interprocess/detail/config_begin.hpp>
|
Chris@16
|
19 #include <boost/interprocess/detail/workaround.hpp>
|
Chris@16
|
20 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
Chris@16
|
21 #include <boost/assert.hpp>
|
Chris@16
|
22 #include <boost/interprocess/detail/atomic.hpp>
|
Chris@16
|
23 #include <boost/cstdint.hpp>
|
Chris@16
|
24 #include <boost/interprocess/detail/os_thread_functions.hpp>
|
Chris@16
|
25 #include <boost/interprocess/sync/spin/wait.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost {
|
Chris@16
|
28 namespace interprocess {
|
Chris@16
|
29 namespace ipcdetail {
|
Chris@16
|
30
|
Chris@16
|
31 class spin_mutex
|
Chris@16
|
32 {
|
Chris@16
|
33 spin_mutex(const spin_mutex &);
|
Chris@16
|
34 spin_mutex &operator=(const spin_mutex &);
|
Chris@16
|
35 public:
|
Chris@16
|
36
|
Chris@16
|
37 spin_mutex();
|
Chris@16
|
38 ~spin_mutex();
|
Chris@16
|
39
|
Chris@16
|
40 void lock();
|
Chris@16
|
41 bool try_lock();
|
Chris@16
|
42 bool timed_lock(const boost::posix_time::ptime &abs_time);
|
Chris@16
|
43 void unlock();
|
Chris@16
|
44 void take_ownership(){};
|
Chris@16
|
45 private:
|
Chris@16
|
46 volatile boost::uint32_t m_s;
|
Chris@16
|
47 };
|
Chris@16
|
48
|
Chris@16
|
49 inline spin_mutex::spin_mutex()
|
Chris@16
|
50 : m_s(0)
|
Chris@16
|
51 {
|
Chris@16
|
52 //Note that this class is initialized to zero.
|
Chris@16
|
53 //So zeroed memory can be interpreted as an
|
Chris@16
|
54 //initialized mutex
|
Chris@16
|
55 }
|
Chris@16
|
56
|
Chris@16
|
57 inline spin_mutex::~spin_mutex()
|
Chris@16
|
58 {
|
Chris@16
|
59 //Trivial destructor
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 inline void spin_mutex::lock(void)
|
Chris@16
|
63 {
|
Chris@16
|
64 spin_wait swait;
|
Chris@16
|
65 do{
|
Chris@16
|
66 boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
|
Chris@16
|
67
|
Chris@16
|
68 if (m_s == 1 && prev_s == 0){
|
Chris@16
|
69 break;
|
Chris@16
|
70 }
|
Chris@16
|
71 // relinquish current timeslice
|
Chris@16
|
72 swait.yield();
|
Chris@16
|
73 }while (true);
|
Chris@16
|
74 }
|
Chris@16
|
75
|
Chris@16
|
76 inline bool spin_mutex::try_lock(void)
|
Chris@16
|
77 {
|
Chris@16
|
78 boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
|
Chris@16
|
79 return m_s == 1 && prev_s == 0;
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
Chris@16
|
83 {
|
Chris@16
|
84 if(abs_time == boost::posix_time::pos_infin){
|
Chris@16
|
85 this->lock();
|
Chris@16
|
86 return true;
|
Chris@16
|
87 }
|
Chris@16
|
88 //Obtain current count and target time
|
Chris@16
|
89 boost::posix_time::ptime now = microsec_clock::universal_time();
|
Chris@16
|
90
|
Chris@16
|
91 spin_wait swait;
|
Chris@16
|
92 do{
|
Chris@16
|
93 if(this->try_lock()){
|
Chris@16
|
94 break;
|
Chris@16
|
95 }
|
Chris@16
|
96 now = microsec_clock::universal_time();
|
Chris@16
|
97
|
Chris@16
|
98 if(now >= abs_time){
|
Chris@16
|
99 return false;
|
Chris@16
|
100 }
|
Chris@16
|
101 // relinquish current time slice
|
Chris@16
|
102 swait.yield();
|
Chris@16
|
103 }while (true);
|
Chris@16
|
104
|
Chris@16
|
105 return true;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 inline void spin_mutex::unlock(void)
|
Chris@16
|
109 { ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); }
|
Chris@16
|
110
|
Chris@16
|
111 } //namespace ipcdetail {
|
Chris@16
|
112 } //namespace interprocess {
|
Chris@16
|
113 } //namespace boost {
|
Chris@16
|
114
|
Chris@16
|
115 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
116
|
Chris@16
|
117 #endif //BOOST_INTERPROCESS_DETAIL_SPIN_MUTEX_HPP
|