@@ -133,50 +133,60 @@ def _make_name():
133133 class _MacOSXSemaphore (SemLock ):
134134 """Dedicated class used only to workaround the missing
135135 function 'sem_getvalue', when interpreter runs on MacOSX.
136- Add a shared counter for each [Bounded]Semaphore in order
137- to handle internal counter when acquire and release operations
138- are called.
136+ Add two shared counters for each [Bounded]Semaphore in order
137+ to calculate the internal value of the semaphore,
138+ when acquire and release operations are called.
139139 """
140140
141141 def __init__ (self , kind , value , maxvalue , * , ctx ):
142142 if not isinstance (self , Semaphore ):
143143 raise TypeError ("_MacOSXSemaphore can only be used "
144144 "as base class of Semaphore class" )
145- self ._count = ctx .Value ('h' , value )
145+ self ._rlock = ctx .RLock ()
146+ self ._count = ctx .Value ('h' , value , lock = self ._rlock )
147+ self ._pending_acquires = ctx .Value ('h' , 0 , lock = self ._rlock )
146148 super ().__init__ (kind , value , maxvalue , ctx = ctx )
147149
148150 def acquire (self , blocking = True , timeout = None ):
151+ with self ._rlock :
152+ self ._pending_acquires .value += 1
149153 if self ._semlock .acquire (blocking , timeout ):
150- with self ._count :
154+ with self ._rlock :
155+ self ._pending_acquires .value -= 1
151156 self ._count .value -= 1
152157 return True
158+ with self ._rlock :
159+ self ._pending_acquires .value -= 1
153160 return False
154161
155162 def release (self ):
156163 if isinstance (self , BoundedSemaphore ):
157- with self ._count :
158- if self ._count .value + 1 > self ._semlock .maxvalue :
159- raise ValueError (f"Cannot exceed initial value of" \
160- f" { self ._semlock .maxvalue !a} " )
161- with self ._count :
164+ with self ._rlock :
165+ if self .get_value () + 1 > self ._semlock .maxvalue :
166+ raise ValueError (f"semaphore released too many times" )
167+ with self ._rlock :
162168 self ._count .value += 1
163169 self ._semlock .release ()
164170
165171 def get_value (self ):
166- return self ._count .value
172+ with self ._rlock :
173+ val = self ._count .value - self ._pending_acquires .value
174+ return val if val > 0 else 0
167175
168176 def _make_methods (self ):
169177 # Do not call the `Semlock._make_methods` method,
170- # as this breaks the reference to the local
178+ # because that breaks the reference to the local
171179 # `acquire` and `release` methods.
172180 pass
173181
174182 def __setstate__ (self , state ):
175- self ._count , state = state [- 1 ], state [:- 1 ]
183+ self ._count , self ._pending_acquires , self ._rlock , state \
184+ = state [- 3 ], state [- 2 ], state [- 1 ], state [:- 3 ]
176185 super ().__setstate__ (state )
177186
178187 def __getstate__ (self ) -> tuple :
179- return super ().__getstate__ () + (self ._count ,)
188+ return super ().__getstate__ () \
189+ + (self ._count , self ._pending_acquires , self ._rlock )
180190
181191
182192 _SemClass = _MacOSXSemaphore
0 commit comments