]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/ReadWriteLock.h
Do not stall if xactions overwrite a recently active cache entry (#516)
[thirdparty/squid.git] / src / ipc / ReadWriteLock.h
1 /*
2 * Copyright (C) 1996-2020 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 #ifndef SQUID_IPC_READ_WRITE_LOCK_H
10 #define SQUID_IPC_READ_WRITE_LOCK_H
11
12 #include <atomic>
13
14 class StoreEntry;
15
16 namespace Ipc
17 {
18
19 class ReadWriteLockStats;
20
21 /// an atomic readers-writer or shared-exclusive lock suitable for maps/tables
22 /// Also supports reading-while-appending mode when readers and writer are
23 /// allowed to access the same locked object because the writer promisses
24 /// to only append new data and all size-related object properties are atomic.
25 class ReadWriteLock
26 {
27 public:
28 ReadWriteLock() : readers(0), writing(false), appending(false), readLevel(0), writeLevel(0)
29 {}
30
31 bool lockShared(); ///< lock for reading or return false
32 bool lockExclusive(); ///< lock for modification or return false
33 bool lockHeaders(); ///< lock for [readable] metadata update or return false
34 void unlockShared(); ///< undo successful sharedLock()
35 void unlockExclusive(); ///< undo successful exclusiveLock()
36 void unlockHeaders(); ///< undo successful lockHeaders()
37 void switchExclusiveToShared(); ///< stop writing, start reading
38 /// same as unlockShared() but also attempts to get a writer lock beforehand
39 /// \returns whether the writer lock was acquired
40 bool unlockSharedAndSwitchToExclusive();
41
42 void startAppending(); ///< writer keeps its lock but also allows reading
43
44 /// adds approximate current stats to the supplied ones
45 void updateStats(ReadWriteLockStats &stats) const;
46
47 public:
48 mutable std::atomic<uint32_t> readers; ///< number of reading users
49 std::atomic<bool> writing; ///< there is a writing user (there can be at most 1)
50 std::atomic<bool> appending; ///< the writer has promised to only append
51 std::atomic_flag updating; ///< a reader is updating metadata/headers
52
53 private:
54 mutable std::atomic<uint32_t> readLevel; ///< number of users reading (or trying to)
55 std::atomic<uint32_t> writeLevel; ///< number of users writing (or trying to write)
56 };
57
58 /// approximate stats of a set of ReadWriteLocks
59 class ReadWriteLockStats
60 {
61 public:
62 ReadWriteLockStats();
63
64 void dump(StoreEntry &e) const;
65
66 int count; ///< the total number of locks
67 int readable; ///< number of locks locked for reading
68 int writeable; ///< number of locks locked for writing
69 int idle; ///< number of unlocked locks
70 int readers; ///< sum of lock.readers
71 int writers; ///< sum of lock.writers
72 int appenders; ///< number of appending writers
73 };
74
75 /// Same as assert(flag is set): The process assert()s if flag is not set.
76 /// Side effect: The unset flag becomes set just before we assert().
77 /// Needed because atomic_flag cannot be compared with a boolean.
78 void AssertFlagIsSet(std::atomic_flag &flag);
79
80 } // namespace Ipc
81
82 #endif /* SQUID_IPC_READ_WRITE_LOCK_H */
83