public function consume($tokens, &$seconds = 0)
    {
        try {
            if ($tokens > $this->capacity) {
                throw new \LengthException("Token amount ($tokens) is larger than the capacity ($this->capacity).");
            }
            if ($tokens <= 0) {
                throw new \InvalidArgumentException("Token amount ($tokens) should be greater than 0.");
            }

            return $this->storage->getMutex()->synchronized(
                function () use ($tokens, &$seconds) {
                    $tokensAndMicrotime = $this->loadTokensAndTimestamp();
                    $microtime = $tokensAndMicrotime["microtime"];
                    $availableTokens = $tokensAndMicrotime["tokens"];

                    $delta = $availableTokens - $tokens;
                    if ($delta < 0) {
                        $this->storage->letMicrotimeUnchanged();
                        $passed  = microtime(true) - $microtime;
                        $seconds = max(0, $this->tokenConverter->convertTokensToSeconds($tokens) - $passed);
                        return false;
                    } else {
                        $microtime += $this->tokenConverter->convertTokensToSeconds($tokens);
                        $this->storage->setMicrotime($microtime);
                        $seconds = 0;
                        return true;
                    }
                }
            );
        } catch (MutexException $e) {
            throw new StorageException("Could not lock token consumption.", 0, $e);
        }
    }