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