Skip to content

Commit e69bfd8

Browse files
committed
last modifications as:
+ Add `pending_acquires` counter + Update comments + Fix nits
1 parent a486952 commit e69bfd8

1 file changed

Lines changed: 24 additions & 14 deletions

File tree

Lib/multiprocessing/synchronize.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)