Issue #850728: Add a *timeout* parameter to the `acquire()` method of
`threading.Semaphore` objects.  Original patch by Torsten Landschoff.
diff --git a/Lib/threading.py b/Lib/threading.py
index b4d07fe..2ca224e 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -290,8 +290,11 @@
         self._cond = Condition(Lock())
         self._value = value
 
-    def acquire(self, blocking=True):
+    def acquire(self, blocking=True, timeout=None):
+        if not blocking and timeout is not None:
+            raise ValueError("can't specify timeout for non-blocking acquire")
         rc = False
+        endtime = None
         self._cond.acquire()
         while self._value == 0:
             if not blocking:
@@ -299,7 +302,14 @@
             if __debug__:
                 self._note("%s.acquire(%s): blocked waiting, value=%s",
                            self, blocking, self._value)
-            self._cond.wait()
+            if timeout is not None:
+                if endtime is None:
+                    endtime = _time() + timeout
+                else:
+                    timeout = endtime - _time()
+                    if timeout <= 0:
+                        break
+            self._cond.wait(timeout)
         else:
             self._value = self._value - 1
             if __debug__: