1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
6 #define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
7 
8 #include <iosfwd>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/callback_helpers.h"
13 #include "base/macros.h"
14 #include "components/services/storage/indexed_db/scopes/scope_lock_range.h"
15 #include "third_party/leveldatabase/src/include/leveldb/comparator.h"
16 #include "third_party/leveldatabase/src/include/leveldb/slice.h"
17 
18 namespace content {
19 
20 // Represents a granted lock in the ScopesLockManager. When this object is
21 // destroyed, the lock is released. Since default construction is supported,
22 // |is_locked()| can be used to inquire locked status. Also, |Release()| can
23 // be called to manually release the lock, which appropriately updates the
24 // |is_locked()| result.
25 class ScopeLock {
26  public:
27   using LockReleasedCallback =
28       base::OnceCallback<void(int level, ScopeLockRange range)>;
29 
30   ScopeLock();
31   ~ScopeLock();
32   ScopeLock(ScopeLock&&) noexcept;
33   // |lock_released_callback| is called when the lock is released, either by
34   // destruction of this object or by the |Released()| call. It will be called
35   // synchronously on the sequence runner this lock is released on.
36   ScopeLock(ScopeLockRange range,
37             int level,
38             LockReleasedCallback lock_released_callback);
39   // The lock in |other| is not released, and |this| must not be holding a lock.
40   ScopeLock& operator=(ScopeLock&& other) noexcept;
41 
42   // Returns true if this object is holding a lock.
is_locked()43   bool is_locked() const { return !lock_released_callback_.is_null(); }
44 
45   // Explicitly releases the granted lock.
46   //
47   // The lock is also released implicitly when this instance is destroyed.
48   // This method is idempotent, i.e. it's valid to call Release() on an
49   // instance that does not hold a granted lock.
50   void Release();
51 
level()52   int level() const { return level_; }
range()53   const ScopeLockRange& range() const { return range_; }
54 
55  private:
56   friend std::ostream& operator<<(std::ostream& out, const ScopeLock& range);
57   friend bool operator==(const ScopeLock& x, const ScopeLock& y);
58   friend bool operator<(const ScopeLock& x, const ScopeLock& y);
59 
60   ScopeLockRange range_;
61   int level_ = 0;
62   // Closure to run when the lock is released. The lock is held when this is
63   // non-null.
64   LockReleasedCallback lock_released_callback_;
65 
66   DISALLOW_COPY_AND_ASSIGN(ScopeLock);
67 };
68 
69 // Logging support.
70 std::ostream& operator<<(std::ostream& out, const ScopeLock& range);
71 
72 // Equality doesn't take into account whether the lock 'is_locked()' or not,
73 // only the level and the range.
74 bool operator==(const ScopeLock& x, const ScopeLock& y);
75 bool operator!=(const ScopeLock& x, const ScopeLock& y);
76 // Comparison operator to allow sorting for locking / unlocking order.
77 bool operator<(const ScopeLock& x, const ScopeLock& y);
78 
79 }  // namespace content
80 
81 #endif  // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
82