MySQL 8.1.0
Source Code Documentation
partitioned_rwlock.h
Go to the documentation of this file.
1#ifndef PARTITIONED_RWLOCK_INCLUDED
2#define PARTITIONED_RWLOCK_INCLUDED
3
4/* Copyright (c) 2015, 2023, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License, version 2.0, for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
26#include <new>
27
28#include "my_compiler.h"
29#include "my_psi_config.h"
31
32/**
33 Implementation of read-write lock partitioned by thread id.
34
35 This rwlock provides better scalability in read-heavy environments by
36 employing the following simple trick:
37 *) Read lock is acquired only on one of its partitions. The specific
38 partition is chosen according to thread id.
39 *) Write lock is acquired on all partitions.
40
41 This way concurrent request for read lock made by different threads
42 have a good chance not to disturb each other by doing cache invalidation
43 and atomic operations. As result scalability in this scenario improves.
44 OTOH acquisition of write lock becomes more expensive. So this rwlock
45 is not supposed to be used in cases when number of write requests is
46 significant.
47*/
48
50 public:
51 Partitioned_rwlock() = default;
52
53 /**
54 @param parts Number of partitions.
55 @param psi_key P_S instrumentation key to use for rwlock instances
56 for partitions.
57 */
58 bool init(uint parts
60 ,
61 PSI_rwlock_key psi_key [[maybe_unused]]
62#endif
63 ) {
64 m_parts = parts;
65 if (!(m_locks_array = new (std::nothrow) mysql_rwlock_t[m_parts]))
66 return true;
67 for (uint i = 0; i < m_parts; ++i)
68 mysql_rwlock_init(psi_key, &m_locks_array[i]);
69 return false;
70 }
71 void destroy() {
72 for (uint i = 0; i < m_parts; ++i) mysql_rwlock_destroy(&m_locks_array[i]);
73 delete[] m_locks_array;
74 }
75 void wrlock() {
76 for (uint i = 0; i < m_parts; ++i) mysql_rwlock_wrlock(&m_locks_array[i]);
77 }
78 void wrunlock() {
79 for (uint i = 0; i < m_parts; ++i) mysql_rwlock_unlock(&m_locks_array[i]);
80 }
81 void rdlock(uint thread_id) {
83 }
84 /*
85 One should use the same thread number for releasing read lock
86 as was used for acquiring it,
87 */
88 void rdunlock(uint thread_id) {
90 }
91
92 private:
94 uint m_parts;
95
96 Partitioned_rwlock(const Partitioned_rwlock &); // Non-copyable
98};
99
100/**
101 Read lock guard class for Partitioned_rwlock. Supports early unlocking.
102*/
103
105 public:
106 /**
107 Acquires read lock on partitioned rwlock on behalf of thread.
108 Automatically release lock in destructor.
109 */
111 : m_rwlock(rwlock), m_thread_id(thread_id) {
113 }
114
117 }
118
119 /** Release read lock. Optional method for early unlocking. */
120 void unlock() {
122 m_rwlock = nullptr;
123 }
124
125 private:
126 /**
127 Pointer to partitioned rwlock which was acquired. NULL if lock was
128 released early so destructor should not do anything.
129 */
131 /**
132 Id of thread on which behalf lock was acquired and which is to be used for
133 unlocking.
134 */
136
137 // Non-copyable
141};
142
143/**
144 Write lock guard class for Partitioned_rwlock. Supports early unlocking.
145*/
146
148 public:
149 /**
150 Acquires write lock on partitioned rwlock.
151 Automatically release it in destructor.
152 */
154 : m_rwlock(rwlock) {
155 m_rwlock->wrlock();
156 }
157
159 if (m_rwlock) m_rwlock->wrunlock();
160 }
161
162 /** Release write lock. Optional method for early unlocking. */
163 void unlock() {
165 m_rwlock = nullptr;
166 }
167
168 private:
169 /**
170 Pointer to partitioned rwlock which was acquired. NULL if lock was
171 released early so destructor should not do anything.
172 */
174
175 // Non-copyable
179};
180
181#endif /* PARTITIONED_RWLOCK_INCLUDED */
Read lock guard class for Partitioned_rwlock.
Definition: partitioned_rwlock.h:104
Partitioned_rwlock_read_guard(const Partitioned_rwlock_read_guard &)
Partitioned_rwlock_read_guard(Partitioned_rwlock *rwlock, uint thread_id)
Acquires read lock on partitioned rwlock on behalf of thread.
Definition: partitioned_rwlock.h:110
Partitioned_rwlock * m_rwlock
Pointer to partitioned rwlock which was acquired.
Definition: partitioned_rwlock.h:130
uint m_thread_id
Id of thread on which behalf lock was acquired and which is to be used for unlocking.
Definition: partitioned_rwlock.h:135
~Partitioned_rwlock_read_guard()
Definition: partitioned_rwlock.h:115
Partitioned_rwlock_read_guard & operator=(const Partitioned_rwlock_read_guard &)
void unlock()
Release read lock.
Definition: partitioned_rwlock.h:120
Write lock guard class for Partitioned_rwlock.
Definition: partitioned_rwlock.h:147
Partitioned_rwlock_write_guard(Partitioned_rwlock *rwlock)
Acquires write lock on partitioned rwlock.
Definition: partitioned_rwlock.h:153
~Partitioned_rwlock_write_guard()
Definition: partitioned_rwlock.h:158
Partitioned_rwlock * m_rwlock
Pointer to partitioned rwlock which was acquired.
Definition: partitioned_rwlock.h:173
Partitioned_rwlock_write_guard & operator=(const Partitioned_rwlock_write_guard &)
void unlock()
Release write lock.
Definition: partitioned_rwlock.h:163
Partitioned_rwlock_write_guard(const Partitioned_rwlock_write_guard &)
Implementation of read-write lock partitioned by thread id.
Definition: partitioned_rwlock.h:49
Partitioned_rwlock(const Partitioned_rwlock &)
void wrlock()
Definition: partitioned_rwlock.h:75
bool init(uint parts, PSI_rwlock_key psi_key)
Definition: partitioned_rwlock.h:58
void wrunlock()
Definition: partitioned_rwlock.h:78
mysql_rwlock_t * m_locks_array
Definition: partitioned_rwlock.h:93
uint m_parts
Definition: partitioned_rwlock.h:94
Partitioned_rwlock()=default
void rdunlock(uint thread_id)
Definition: partitioned_rwlock.h:88
void destroy()
Definition: partitioned_rwlock.h:71
Partitioned_rwlock & operator=(const Partitioned_rwlock &)
void rdlock(uint thread_id)
Definition: partitioned_rwlock.h:81
#define mysql_rwlock_rdlock(T)
Definition: mysql_rwlock.h:60
#define mysql_rwlock_unlock(T)
Definition: mysql_rwlock.h:90
#define mysql_rwlock_init(K, T)
Definition: mysql_rwlock.h:40
#define mysql_rwlock_destroy(T)
Definition: mysql_rwlock.h:50
#define mysql_rwlock_wrlock(T)
Definition: mysql_rwlock.h:70
unsigned int PSI_rwlock_key
Instrumented rwlock key.
Definition: psi_rwlock_bits.h:43
Header for compiler-dependent features.
Defines various enable/disable and HAVE_ macros related to the performance schema instrumentation sys...
#define HAVE_PSI_INTERFACE
Definition: my_psi_config.h:38
static my_thread_id thread_id
Definition: my_thr_init.cc:62
Instrumentation helpers for rwlock.
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:50