@@ -123,21 +123,89 @@ def _make_name():
123123 return '%s-%s' % (process .current_process ()._config ['semprefix' ],
124124 next (SemLock ._rand ))
125125
126+ if sys .platform == 'darwin' :
127+ #
128+ # Specific MacOSX Semaphore
129+ #
130+
131+ class _MacOSXSemaphore (SemLock ):
132+ """Dedicated class used only to workaround the missing
133+ function 'sem_getvalue', when interpreter runs on MacOSX.
134+ Add a shared counter for each [Bounded]Semaphore in order
135+ to handle internal counter when acquire and release operations
136+ are called.
137+ """
138+
139+ def __init__ (self , kind , value , maxvalue , * , ctx ):
140+ util .debug (f"_MacOSXSemaphore:: creation of a { self .__class__ .__name__ } " \
141+ f"with '{ value = } '" )
142+ SemLock .__init__ (self , kind , value , maxvalue , ctx = ctx )
143+ self ._count = ctx .Value ('L' , value ) # May be more than 'L' ?
144+
145+ def _acquire (self , * args , ** kwargs ) -> bool :
146+ if self ._semlock .acquire (* args , ** kwargs ):
147+ with self ._count :
148+ util .debug (f"_MacOSXSemaphore: acquire { repr (self )} " )
149+ self ._count .value -= 1
150+ return True
151+ return False
152+
153+ def _release (self ):
154+ with self ._count :
155+ self ._count .value += 1
156+ self ._semlock .release ()
157+ util .debug (f"_MacOSXSemaphore: release { repr (self )} " )
158+
159+ def _release_bounded (self ):
160+ if self ._count .value + 1 > self ._semlock .maxvalue :
161+ raise ValueError (f"Cannot exceed initial value of" \
162+ f" { self ._semlock .maxvalue !a} " )
163+ self ._release ()
164+
165+ def _get_value (self ) -> int :
166+ return self ._count .value
167+
168+ def _make_methods (self ):
169+ super ()._make_methods ()
170+ util .debug ("_MacOSXSemaphore: _make_methods call" )
171+ self .acquire = self ._acquire
172+ if isinstance (self , BoundedSemaphore ):
173+ self .release = self ._release_bounded
174+ elif isinstance (self , Semaphore ):
175+ self .release = self ._release
176+ else :
177+ raise RuntimeError ("Class dedicated only to Semaphore or BoundedSemaphore OSX" )
178+ self .get_value = self ._get_value
179+
180+ def __setstate__ (self , state ):
181+ self ._count , state = state [- 1 ], state [:- 1 ]
182+ super ().__setstate__ (state )
183+
184+ def __getstate__ (self ) -> tuple :
185+ return super ().__getstate__ () + (self ._count ,)
186+
187+
188+ _SemClass = _MacOSXSemaphore
189+ else :
190+ _SemClass = SemLock
191+
126192#
127193# Semaphore
128194#
129195
130- class Semaphore (SemLock ):
196+ class Semaphore (_SemClass ):
131197
132198 def __init__ (self , value = 1 , * , ctx ):
133- SemLock .__init__ (self , SEMAPHORE , value , SEM_VALUE_MAX , ctx = ctx )
199+ _SemClass .__init__ (self , SEMAPHORE , value , SEM_VALUE_MAX , ctx = ctx )
134200
135201 def get_value (self ):
202+ """redefined when MacOSX.
203+ """
136204 return self ._semlock ._get_value ()
137205
138206 def __repr__ (self ):
139207 try :
140- value = self ._semlock . _get_value ()
208+ value = self .get_value ()
141209 except Exception :
142210 value = 'unknown'
143211 return '<%s(value=%s)>' % (self .__class__ .__name__ , value )
@@ -149,11 +217,11 @@ def __repr__(self):
149217class BoundedSemaphore (Semaphore ):
150218
151219 def __init__ (self , value = 1 , * , ctx ):
152- SemLock .__init__ (self , SEMAPHORE , value , value , ctx = ctx )
220+ _SemClass .__init__ (self , SEMAPHORE , value , value , ctx = ctx )
153221
154222 def __repr__ (self ):
155223 try :
156- value = self ._semlock . _get_value ()
224+ value = self .get_value ()
157225 except Exception :
158226 value = 'unknown'
159227 return '<%s(value=%s, maxvalue=%s)>' % \
0 commit comments