ReadWriteLock.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 54 Interprocess Communication */
10
11#include "squid.h"
12#include "ipc/ReadWriteLock.h"
13#include "Store.h"
14
15void Ipc::AssertFlagIsSet(std::atomic_flag &flag)
16{
17 // If the flag was false, then we set it to true and assert. A true flag
18 // may help keep other processes away from this broken entry.
19 // Otherwise, we just set an already set flag, which is probably a no-op.
20 assert(flag.test_and_set(std::memory_order_relaxed));
21}
22
27bool
29{
30 assert(writeLevel); // "new" readers are locked out by the caller
31 assert(!appending); // nobody can be appending without an exclusive lock
32 if (!readLevel) { // no old readers and nobody is becoming a reader
33 writing = true;
34 return true;
35 }
36 --writeLevel;
37 return false;
38}
39
40bool
42{
43 ++readLevel; // this locks "new" writers out
44 if (!writeLevel || appending) { // nobody is writing, or sharing is OK
45 ++readers;
46 return true;
47 }
48 --readLevel;
49 return false;
50}
51
52bool
54{
55 if (!writeLevel++) // we are the first writer + lock "new" readers out
56 return finalizeExclusive(); // decrements writeLevel on failures
57
58 --writeLevel;
59 return false;
60}
61
62bool
64{
65 if (lockShared()) {
66 if (!updating.test_and_set(std::memory_order_acquire))
67 return true; // we got here first
68 // the updating lock was already set by somebody else
69 unlockShared();
70 }
71 return false;
72}
73
74void
76{
77 assert(readers > 0);
78 --readers;
79 --readLevel;
80}
81
82void
84{
85 assert(writing);
86 appending = false;
87 writing = false;
88 --writeLevel;
89}
90
91void
93{
94 AssertFlagIsSet(updating);
95 updating.clear(std::memory_order_release);
96 unlockShared();
97}
98
99void
101{
102 assert(writing);
103 ++readLevel; // must be done before we release exclusive control
104 ++readers;
105 unlockExclusive();
106}
107
108bool
110{
111 assert(readers > 0);
112 if (!writeLevel++) { // we are the first writer + lock "new" readers out
113 unlockShared();
114 return finalizeExclusive(); // decrements writeLevel on failures
115 }
116
117 // somebody is still writing, so we just stop reading
118 unlockShared();
119 --writeLevel;
120 return false;
121}
122
123void
125{
126 assert(writing);
127 appending = true;
128}
129
130void
132{
133 if (readers) {
134 ++stats.readable;
135 stats.readers += readers;
136 } else if (writing) {
137 ++stats.writeable;
138 ++stats.writers;
139 stats.appenders += appending;
140 } else {
141 ++stats.idle;
142 }
143 ++stats.count;
144}
145
146/* Ipc::ReadWriteLockStats */
147
149{
150 memset(this, 0, sizeof(*this));
151}
152
153void
155{
156 storeAppendPrintf(&e, "Available locks: %9d\n", count);
157
158 if (!count)
159 return;
160
161 storeAppendPrintf(&e, "Reading: %9d %6.2f%%\n",
162 readable, (100.0 * readable / count));
163 storeAppendPrintf(&e, "Writing: %9d %6.2f%%\n",
164 writeable, (100.0 * writeable / count));
165 storeAppendPrintf(&e, "Idle: %9d %6.2f%%\n",
166 idle, (100.0 * idle / count));
167
168 if (readers || writers) {
169 const int locked = readers + writers;
170 storeAppendPrintf(&e, "Readers: %9d %6.2f%%\n",
171 readers, (100.0 * readers / locked));
172 const double appPerc = writers ? (100.0 * appenders / writers) : 0.0;
173 storeAppendPrintf(&e, "Writers: %9d %6.2f%% including Appenders: %9d %6.2f%%\n",
174 writers, (100.0 * writers / locked),
175 appenders, appPerc);
176 }
177}
178
179std::ostream &
180Ipc::operator <<(std::ostream &os, const Ipc::ReadWriteLock &lock)
181{
182 return os << lock.readers << 'R' <<
183 (lock.writing ? "W" : "") <<
184 (lock.appending ? "A" : "");
185 // impossible to report lock.updating without setting/clearing that flag
186}
187
#define assert(EX)
Definition: assert.h:17
approximate stats of a set of ReadWriteLocks
Definition: ReadWriteLock.h:66
void dump(StoreEntry &e) const
void unlockHeaders()
undo successful lockHeaders()
std::atomic< uint32_t > readLevel
number of users reading (or trying to)
Definition: ReadWriteLock.h:57
void switchExclusiveToShared()
bool lockHeaders()
lock for [readable] metadata update or return false
std::atomic< uint32_t > readers
number of reading users
Definition: ReadWriteLock.h:49
void unlockExclusive()
undo successful exclusiveLock()
bool lockExclusive()
lock for modification or return false
std::atomic< uint32_t > writeLevel
number of users writing (or trying to write)
Definition: ReadWriteLock.h:58
std::atomic< bool > writing
there is a writing user (there can be at most 1)
Definition: ReadWriteLock.h:50
bool unlockSharedAndSwitchToExclusive()
std::atomic< bool > appending
the writer has promised to only append
Definition: ReadWriteLock.h:51
void unlockShared()
undo successful sharedLock()
bool lockShared()
lock for reading or return false
void updateStats(ReadWriteLockStats &stats) const
adds approximate current stats to the supplied ones
void startAppending()
writer keeps its lock but also allows reading
void AssertFlagIsSet(std::atomic_flag &flag)
std::ostream & operator<<(std::ostream &os, const QuestionerId &qid)
Definition: QuestionerId.h:63
class Ping::pingStats_ stats
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:829

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors