text: // Copyright 2018 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
  #define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
  
  #include <iosfwd>
  
  #include "base/callback.h"
  #include "base/callback_helpers.h"
  #include "base/macros.h"
  #include "components/services/storage/indexed_db/scopes/scope_lock_range.h"
  #include "third_party/leveldatabase/src/include/leveldb/comparator.h"
  #include "third_party/leveldatabase/src/include/leveldb/slice.h"
  
  namespace content {
  
  // Represents a granted lock in the ScopesLockManager. When this object is
  // destroyed, the lock is released. Since default construction is supported,
  // |is_locked()| can be used to inquire locked status. Also, |Release()| can
  // be called to manually release the lock, which appropriately updates the
  // |is_locked()| result.
  class ScopeLock {
   public:
    using LockReleasedCallback =
        base::OnceCallback<void(int level, ScopeLockRange range)>;
  
    ScopeLock();
    ~ScopeLock();
    ScopeLock(ScopeLock&&) noexcept;
    // |lock_released_callback| is called when the lock is released, either by
    // destruction of this object or by the |Released()| call. It will be called
    // synchronously on the sequence runner this lock is released on.
    ScopeLock(ScopeLockRange range,
              int level,
              LockReleasedCallback lock_released_callback);
    // The lock in |other| is not released, and |this| must not be holding a lock.
    ScopeLock& operator=(ScopeLock&& other) noexcept;
  
    // Returns true if this object is holding a lock.
    bool is_locked() const { return !lock_released_callback_.is_null(); }
  
    // Explicitly releases the granted lock.
    //
    // The lock is also released implicitly when this instance is destroyed.
    // This method is idempotent, i.e. it's valid to call Release() on an
    // instance that does not hold a granted lock.
    void Release();
  
    int level() const { return level_; }
    const ScopeLockRange& range() const { return range_; }
  
   private:
    friend std::ostream& operator<<(std::ostream& out, const ScopeLock& range);
    friend bool operator==(const ScopeLock& x, const ScopeLock& y);
    friend bool operator<(const ScopeLock& x, const ScopeLock& y);
  
    ScopeLockRange range_;
    int level_ = 0;
    // Closure to run when the lock is released. The lock is held when this is
    // non-null.
    LockReleasedCallback lock_released_callback_;
  
    DISALLOW_COPY_AND_ASSIGN(ScopeLock);
  };
  
  // Logging support.
  std::ostream& operator<<(std::ostream& out, const ScopeLock& range);
  
  // Equality doesn't take into account whether the lock 'is_locked()' or not,
  // only the level and the range.
  bool operator==(const ScopeLock& x, const ScopeLock& y);
  bool operator!=(const ScopeLock& x, const ScopeLock& y);
  // Comparison operator to allow sorting for locking / unlocking order.
  bool operator<(const ScopeLock& x, const ScopeLock& y);
  
  }  // namespace content
  
  #endif  // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
  