]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
11 | #ifndef BOOST_INTERPROCESS_SEMAPHORE_HPP | |
12 | #define BOOST_INTERPROCESS_SEMAPHORE_HPP | |
13 | ||
14 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
15 | ||
16 | #ifndef BOOST_CONFIG_HPP | |
17 | # include <boost/config.hpp> | |
18 | #endif | |
19 | # | |
20 | #if defined(BOOST_HAS_PRAGMA_ONCE) | |
21 | # pragma once | |
22 | #endif | |
23 | ||
24 | #include <boost/interprocess/detail/config_begin.hpp> | |
25 | #include <boost/interprocess/detail/workaround.hpp> | |
26 | ||
27 | #include <boost/interprocess/creation_tags.hpp> | |
28 | #include <boost/interprocess/exceptions.hpp> | |
29 | #include <boost/interprocess/detail/posix_time_types_wrk.hpp> | |
30 | ||
31 | #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \ | |
32 | (defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES)) | |
33 | #include <boost/interprocess/sync/posix/semaphore.hpp> | |
34 | #define BOOST_INTERPROCESS_USE_POSIX | |
35 | //Experimental... | |
36 | #elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) | |
37 | #include <boost/interprocess/sync/windows/semaphore.hpp> | |
38 | #define BOOST_INTERPROCESS_USE_WINDOWS | |
39 | #elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
40 | #include <boost/interprocess/sync/spin/semaphore.hpp> | |
41 | #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION | |
42 | #endif | |
43 | ||
44 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
45 | ||
46 | //!\file | |
47 | //!Describes a interprocess_semaphore class for inter-process synchronization | |
48 | ||
49 | namespace boost { | |
50 | namespace interprocess { | |
51 | ||
52 | //!Wraps a interprocess_semaphore that can be placed in shared memory and can be | |
53 | //!shared between processes. Allows timed lock tries | |
54 | class interprocess_semaphore | |
55 | { | |
56 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
57 | //Non-copyable | |
58 | interprocess_semaphore(const interprocess_semaphore &); | |
59 | interprocess_semaphore &operator=(const interprocess_semaphore &); | |
60 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
61 | public: | |
62 | //!Creates a interprocess_semaphore with the given initial count. | |
63 | //!interprocess_exception if there is an error.*/ | |
64 | interprocess_semaphore(unsigned int initialCount); | |
65 | ||
66 | //!Destroys the interprocess_semaphore. | |
67 | //!Does not throw | |
68 | ~interprocess_semaphore(); | |
69 | ||
70 | //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting | |
71 | //!for the interprocess_semaphore, then one of these processes will return successfully from | |
72 | //!its wait function. If there is an error an interprocess_exception exception is thrown. | |
73 | void post(); | |
74 | ||
75 | //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, | |
76 | //!then the calling process/thread blocks until it can decrement the counter. | |
77 | //!If there is an error an interprocess_exception exception is thrown. | |
78 | void wait(); | |
79 | ||
80 | //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero | |
81 | //!and returns true. If the value is not greater than zero returns false. | |
82 | //!If there is an error an interprocess_exception exception is thrown. | |
83 | bool try_wait(); | |
84 | ||
85 | //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater | |
86 | //!than zero and returns true. Otherwise, waits for the interprocess_semaphore | |
87 | //!to the posted or the timeout expires. If the timeout expires, the | |
88 | //!function returns false. If the interprocess_semaphore is posted the function | |
89 | //!returns true. If there is an error throws sem_exception | |
90 | bool timed_wait(const boost::posix_time::ptime &abs_time); | |
91 | ||
92 | //!Returns the interprocess_semaphore count | |
93 | // int get_count() const; | |
94 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
95 | private: | |
96 | #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) | |
97 | #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION | |
98 | ipcdetail::spin_semaphore m_sem; | |
99 | #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) | |
100 | #undef BOOST_INTERPROCESS_USE_WINDOWS | |
101 | ipcdetail::windows_semaphore m_sem; | |
102 | #else | |
103 | #undef BOOST_INTERPROCESS_USE_POSIX | |
104 | ipcdetail::posix_semaphore m_sem; | |
105 | #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) | |
106 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
107 | }; | |
108 | ||
109 | } //namespace interprocess { | |
110 | } //namespace boost { | |
111 | ||
112 | namespace boost { | |
113 | namespace interprocess { | |
114 | ||
115 | inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount) | |
116 | : m_sem(initialCount) | |
117 | {} | |
118 | ||
119 | inline interprocess_semaphore::~interprocess_semaphore(){} | |
120 | ||
121 | inline void interprocess_semaphore::wait() | |
122 | { | |
123 | #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING | |
124 | boost::posix_time::ptime wait_time | |
125 | = microsec_clock::universal_time() | |
126 | + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS); | |
127 | if (!m_sem.timed_wait(wait_time)) | |
128 | { | |
129 | throw interprocess_exception(timeout_when_waiting_error, "Interprocess semaphore timeout when waiting. Possible deadlock: owner died without posting?"); | |
130 | } | |
131 | #else | |
132 | m_sem.wait(); | |
133 | #endif | |
134 | } | |
135 | inline bool interprocess_semaphore::try_wait() | |
136 | { return m_sem.try_wait(); } | |
137 | ||
138 | inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) | |
139 | { return m_sem.timed_wait(abs_time); } | |
140 | ||
141 | inline void interprocess_semaphore::post() | |
142 | { m_sem.post(); } | |
143 | ||
144 | } //namespace interprocess { | |
145 | } //namespace boost { | |
146 | ||
147 | #include <boost/interprocess/detail/config_end.hpp> | |
148 | ||
149 | #endif //BOOST_INTERPROCESS_SEMAPHORE_HPP |