MySQL 9.1.0
Source Code Documentation
gcs_tagged_lock.h
Go to the documentation of this file.
1/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef GCS_TAGGED_LOCK_INCLUDED
25#define GCS_TAGGED_LOCK_INCLUDED
26
27#include <atomic> // std::atomic
28#include <cstdint> // std::uint64_t
29
30/**
31 * @brief The Gcs_tagged_lock class
32 * Implements a tagged lock for optimistic read-side sections.
33 *
34 * In a nutshell, the tagged lock is a read-write spin lock which offers the
35 * following API:
36 *
37 * try_lock() -> bool
38 * unlock()
39 * optimistic_read() -> tag
40 * validate_optimistic_read(tag) -> bool
41 *
42 * For the write-side section, one uses it as a typical spin lock, e.g.:
43 *
44 * do:
45 * lock_acquired := try_lock()
46 * while (not lock_acquired)
47 * write-side section
48 * unlock()
49 *
50 * For the read-side section, one can use it as follows:
51 *
52 * done := false
53 * while (not done):
54 * tag := optimistic_read()
55 * unsynchronised read-side section
56 * done := validate_optimistic_read(tag)
57 * if (not done):
58 * rollback unsynchronized read-side section
59 *
60 * The idea is to allow an optimistic read-side section that does not perform
61 * any memory stores.
62 * This is in contrast with a typical read-write lock, where the read side
63 * performs some memory stores to account for the reader, e.g. keeping a reader
64 * counter.
65 * The trade off is that:
66 *
67 * a. the execution of the read-side of a tagged lock may be concurrent with
68 * the write-side section if meanwhile the tagged lock is acquired
69 * b. the read-side of a tagged lock may fail if meanwhile the tagged lock is
70 * acquired, in which case one may want to rollback the effects of the
71 * failed read-side section
72 *
73 * The tagged lock is implemented over a single atomic 64-bit word with the
74 * following bit layout:
75 *
76 * bit # 64 63 62 3 2 1
77 * +---+---+---+-...-+---+---+---+
78 * | | | | | | | |
79 * +---+---+---+-...-+---+---+---+
80 * \__________ ___________/ \ /
81 * \/ v
82 * tag locked?
83 */
85 public:
86 using Tag = std::uint64_t;
87
88 Gcs_tagged_lock() noexcept;
90
91 /**
92 * Starts an optimistic read-side section.
93 * @returns the tag associated with the optimistic execution.
94 */
95 Tag optimistic_read() const;
96
97 /**
98 * Validates an optimistic read-side section.
99 * @param tag The tag returned by the corresponding @c optimistic_read
100 * @returns true if the optimistic read-side was atomically executed while the
101 * lock was free, false otherwise
102 */
103 bool validate_optimistic_read(Tag const &tag) const;
104
105 /**
106 * Attempts to start a write-side section, i.e. acquire the lock.
107 * @returns true if the write-side section was successfully started, i.e. we
108 * acquired the lock, false otherwise
109 */
110 bool try_lock();
111
112 /**
113 * Finishes the write-side section, i.e. releases the lock.
114 */
115 void unlock();
116
117 /**
118 * Checks whether the lock is currently acquired.
119 * @returns true if the lock is currently acquired, false otherwise
120 */
121 bool is_locked() const;
122
123 private:
124 /*
125 * Atomically loads the underlying lock word.
126 */
127 std::uint64_t get_lock_word(
128 std::memory_order order = std::memory_order_acquire) const;
129
130 /* The underlying lock word. */
131 std::atomic<std::uint64_t> m_lock_word;
132};
133
134#endif // GCS_TAGGED_LOCK_INCLUDED
The Gcs_tagged_lock class Implements a tagged lock for optimistic read-side sections.
Definition: gcs_tagged_lock.h:84
std::uint64_t Tag
Definition: gcs_tagged_lock.h:86
bool validate_optimistic_read(Tag const &tag) const
Validates an optimistic read-side section.
Definition: gcs_tagged_lock.cc:71
std::atomic< std::uint64_t > m_lock_word
Definition: gcs_tagged_lock.h:131
void unlock()
Finishes the write-side section, i.e.
Definition: gcs_tagged_lock.cc:110
std::uint64_t get_lock_word(std::memory_order order=std::memory_order_acquire) const
Definition: gcs_tagged_lock.cc:30
Tag optimistic_read() const
Starts an optimistic read-side section.
Definition: gcs_tagged_lock.cc:44
bool is_locked() const
Checks whether the lock is currently acquired.
Definition: gcs_tagged_lock.cc:115
bool try_lock()
Attempts to start a write-side section, i.e.
Definition: gcs_tagged_lock.cc:100
Gcs_tagged_lock() noexcept
Definition: gcs_tagged_lock.cc:26
Definition: gcs_xcom_synode.h:64