def wait_for(self, predicate, timeout=None):
        """Like :meth:`wait` but additionally for *predicate* to be true.

        The *predicate* argument must be a callable that takes no arguments.
        Its result is interpreted as a boolean value.
        """
        if not is_locked(self._lock):
            raise RuntimeError('lock is not locked')
        hub = get_hub()
        try:
            with switch_back(timeout, lock=thread_lock(self._lock)) as switcher:
                handle = add_callback(self, switcher, predicate)
                # See the comment in Lock.acquire() why it is OK to release the
                # lock here before calling hub.switch().
                # Also if this is a reentrant lock make sure it is fully released.
                state = release_save(self._lock)
                hub.switch()
        except BaseException as e:
            with self._lock:
                remove_callback(self, handle)
            if e is switcher.timeout:
                return False
            raise
        finally:
            acquire_restore(self._lock, state)
        return True