def release_shared(self):
        """
        Releases the lock previously locked by a call to acquire_shared().
        Returns None.
        """

        thrCurrent = currentThread()

        self._lock()
        try:

            if self.__log: self._log("releasing shared")
            if self.__debug:
                assert self._invariant(), "SharedLock invariant failed: %s in %s" % \
                                          (self._debug_dump(), trace_string())

            if thrCurrent not in self.dicUsers:
                raise Exception("Current thread has not acquired the lock")
                
            # the thread releases its shared lock

            self.dicUsers[thrCurrent] -= 1
            if self.dicUsers[thrCurrent] > 0:
                if self.__debug:
                    assert self._invariant(), "SharedLock invariant failed: %s in %s" % \
                                              (self._debug_dump(), trace_string())
                if self.__log: self._log("released shared")
                return
            else:
                del self.dicUsers[thrCurrent]

            # a decision is made which pending thread(s) to awake (if any)

            self._release_threads()
            
            if self.__debug:
                assert self._invariant(), "SharedLock invariant failed: %s in %s" % \
                                          (self._debug_dump(), trace_string())
            if self.__log: self._log("released shared")

        finally:
            self._unlock()

        Releases the lock previously locked by a call to acquire_shared().
        Returns None.
        
recipes/Python/465156_Shared_lock_akreaderwriter_lock_timeouts_FIFO/recipe-465156.py