/*
- * 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.
#ifndef SQUID_IPC_READ_WRITE_LOCK_H
#define SQUID_IPC_READ_WRITE_LOCK_H
-#include "ipc/AtomicWord.h"
+#include <atomic>
+#include <iosfwd>
class StoreEntry;
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
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
{
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 */