MySQL  8.0.21
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, 2019, Oracle and/or its affiliates. All rights reserved.
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"
30 #include "mysql/psi/mysql_rwlock.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:
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
59 #ifdef HAVE_PSI_INTERFACE
60  ,
61  PSI_rwlock_key psi_key MY_ATTRIBUTE((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  }
83  }
84  /*
85  One should use the same thread number for releasing read lock
86  as was used for acquiring it,
87  */
90  }
91 
92  private:
95 
96  Partitioned_rwlock(const Partitioned_rwlock &); // Non-copyable
97  Partitioned_rwlock &operator=(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) {
112  m_rwlock->rdlock(m_thread_id);
113  }
114 
116  if (m_rwlock) m_rwlock->rdunlock(m_thread_id);
117  }
118 
119  /** Release read lock. Optional method for early unlocking. */
120  void unlock() {
121  m_rwlock->rdunlock(m_thread_id);
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() {
164  m_rwlock->wrunlock();
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 */
#define mysql_rwlock_init(K, T)
Definition: mysql_rwlock.h:40
void wrunlock()
Definition: partitioned_rwlock.h:78
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()
Definition: partitioned_rwlock.h:51
void destroy()
Definition: partitioned_rwlock.h:71
Read lock guard class for Partitioned_rwlock.
Definition: partitioned_rwlock.h:104
mysql_rwlock_t * m_locks_array
Definition: partitioned_rwlock.h:93
bool init(uint parts, PSI_rwlock_key psi_key)
Definition: partitioned_rwlock.h:58
void rdlock(uint thread_id)
Definition: partitioned_rwlock.h:81
void unlock()
Release read lock.
Definition: partitioned_rwlock.h:120
Partitioned_rwlock & operator=(const Partitioned_rwlock &)
Instrumentation helpers for rwlock.
void wrlock()
Definition: partitioned_rwlock.h:75
#define mysql_rwlock_unlock(T)
Definition: mysql_rwlock.h:90
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
uint m_parts
Definition: partitioned_rwlock.h:94
Write lock guard class for Partitioned_rwlock.
Definition: partitioned_rwlock.h:147
Header for compiler-dependent features.
~Partitioned_rwlock_read_guard()
Definition: partitioned_rwlock.h:115
Defines various enable/disable and HAVE_ macros related to the performance schema instrumentation sys...
unsigned int uint
Definition: uca-dump.cc:29
#define mysql_rwlock_destroy(T)
Definition: mysql_rwlock.h:50
unsigned int PSI_rwlock_key
Instrumented rwlock key.
Definition: psi_rwlock_bits.h:41
#define HAVE_PSI_INTERFACE
Definition: my_psi_config.h:38
Partitioned_rwlock * m_rwlock
Pointer to partitioned rwlock which was acquired.
Definition: partitioned_rwlock.h:173
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:50
~Partitioned_rwlock_write_guard()
Definition: partitioned_rwlock.h:158
Partitioned_rwlock_write_guard(Partitioned_rwlock *rwlock)
Acquires write lock on partitioned rwlock.
Definition: partitioned_rwlock.h:153
#define mysql_rwlock_wrlock(T)
Definition: mysql_rwlock.h:70
Implementation of read-write lock partitioned by thread id.
Definition: partitioned_rwlock.h:49
void rdunlock(uint thread_id)
Definition: partitioned_rwlock.h:88
Partitioned_rwlock * m_rwlock
Pointer to partitioned rwlock which was acquired.
Definition: partitioned_rwlock.h:130
#define mysql_rwlock_rdlock(T)
Definition: mysql_rwlock.h:60
static my_thread_id thread_id
Definition: my_thr_init.cc:62
void unlock()
Release write lock.
Definition: partitioned_rwlock.h:163