]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/ipc/ReadWriteLock.h
paranoid_hit_validation directive (#559)
[thirdparty/squid.git] / src / ipc / ReadWriteLock.h
index 65ec41b5867ab188726a84f56d0fa6ce040c7c54..3233882255567579f47f9e768dd64b4d075fa4ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -9,7 +9,8 @@
 #ifndef SQUID_IPC_READ_WRITE_LOCK_H
 #define SQUID_IPC_READ_WRITE_LOCK_H
 
-#include "ipc/AtomicWord.h"
+#include <atomic>
+#include <iosfwd>
 
 class StoreEntry;
 
@@ -25,13 +26,19 @@ class ReadWriteLockStats;
 class ReadWriteLock
 {
 public:
-    // default constructor is OK because of shared memory zero-initialization
+    ReadWriteLock() : readers(0), writing(false), appending(false), readLevel(0), writeLevel(0)
+    {}
 
     bool lockShared(); ///< lock for reading or return false
     bool lockExclusive(); ///< lock for modification or return false
+    bool lockHeaders(); ///< lock for [readable] metadata update or return false
     void unlockShared(); ///< undo successful sharedLock()
     void unlockExclusive(); ///< undo successful exclusiveLock()
+    void unlockHeaders(); ///< undo successful lockHeaders()
     void switchExclusiveToShared(); ///< stop writing, start reading
+    /// same as unlockShared() but also attempts to get a writer lock beforehand
+    /// \returns whether the writer lock was acquired
+    bool unlockSharedAndSwitchToExclusive();
 
     void startAppending(); ///< writer keeps its lock but also allows reading
 
@@ -39,15 +46,19 @@ public:
     void updateStats(ReadWriteLockStats &stats) const;
 
 public:
-    mutable Atomic::Word readers; ///< number of reading users
-    Atomic::Word writing; ///< there is a writing user (there can be at most 1)
-    Atomic::Word appending; ///< the writer has promissed to only append
+    mutable std::atomic<uint32_t> readers; ///< number of reading users
+    std::atomic<bool> writing; ///< there is a writing user (there can be at most 1)
+    std::atomic<bool> appending; ///< the writer has promised to only append
+    std::atomic_flag updating; ///< a reader is updating metadata/headers
 
 private:
-    mutable Atomic::Word readLevel; ///< number of users reading (or trying to)
-    Atomic::Word writeLevel; ///< number of users writing (or trying to write)
+    mutable std::atomic<uint32_t> readLevel; ///< number of users reading (or trying to)
+    std::atomic<uint32_t> writeLevel; ///< number of users writing (or trying to write)
 };
 
+/// dumps approximate lock state (for debugging)
+std::ostream &operator <<(std::ostream &os, const Ipc::ReadWriteLock &);
+
 /// approximate stats of a set of ReadWriteLocks
 class ReadWriteLockStats
 {
@@ -65,6 +76,11 @@ public:
     int appenders; ///< number of appending writers
 };
 
+/// Same as assert(flag is set): The process assert()s if flag is not set.
+/// Side effect: The unset flag becomes set just before we assert().
+/// Needed because atomic_flag cannot be compared with a boolean.
+void AssertFlagIsSet(std::atomic_flag &flag);
+
 } // namespace Ipc
 
 #endif /* SQUID_IPC_READ_WRITE_LOCK_H */