From 596c513d3e9a4a252bfd67e9074ca75f4d7a64f8 Mon Sep 17 00:00:00 2001 From: Malavan Sotheeswaran Date: Mon, 25 Sep 2023 15:53:47 -0400 Subject: [PATCH] only use internal locks when multithreaded (#205) --- src/ae.cpp | 2 +- src/readwritelock.h | 80 ++++++++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/ae.cpp b/src/ae.cpp index 99093daa8..86f82a935 100644 --- a/src/ae.cpp +++ b/src/ae.cpp @@ -861,7 +861,7 @@ void aeReleaseForkLock() void aeForkLockInChild() { - g_forkLock.setNotify(false); + g_forkLock.setMulti(false); } int aeThreadOwnsLock() diff --git a/src/readwritelock.h b/src/readwritelock.h index 79f0ac710..05385e4e7 100644 --- a/src/readwritelock.h +++ b/src/readwritelock.h @@ -8,38 +8,46 @@ class readWriteLock { int m_readCount = 0; int m_writeCount = 0; bool m_writeWaiting = false; - bool m_notify = true; + bool m_multi = true; public: readWriteLock(const char *name) : m_readLock(name), m_writeLock(name) {} void acquireRead() { - std::unique_lock rm(m_readLock); - while (m_writeCount > 0 || m_writeWaiting) - m_cv.wait(rm); + std::unique_lock rm(m_readLock, std::defer_lock); + if (m_multi) { + rm.lock(); + while (m_writeCount > 0 || m_writeWaiting) + m_cv.wait(rm); + } m_readCount++; } bool tryAcquireRead() { std::unique_lock rm(m_readLock, std::defer_lock); - if (!rm.try_lock()) - return false; - if (m_writeCount > 0 || m_writeWaiting) - return false; + if (m_multi) { + if (!rm.try_lock()) + return false; + if (m_writeCount > 0 || m_writeWaiting) + return false; + } m_readCount++; return true; } void acquireWrite(bool exclusive = true) { - std::unique_lock rm(m_readLock); - m_writeWaiting = true; - while (m_readCount > 0) - m_cv.wait(rm); - if (exclusive) { - /* Another thread might have the write lock while we have the read lock - but won't be able to release it until they can acquire the read lock - so release the read lock and try again instead of waiting to avoid deadlock */ - while(!m_writeLock.try_lock()) + std::unique_lock rm(m_readLock, std::defer_lock); + if (m_multi) { + rm.lock(); + m_writeWaiting = true; + while (m_readCount > 0) m_cv.wait(rm); + if (exclusive) { + /* Another thread might have the write lock while we have the read lock + but won't be able to release it until they can acquire the read lock + so release the read lock and try again instead of waiting to avoid deadlock */ + while(!m_writeLock.try_lock()) + m_cv.wait(rm); + } } m_writeCount++; m_writeWaiting = false; @@ -52,32 +60,38 @@ class readWriteLock { bool tryAcquireWrite(bool exclusive = true) { std::unique_lock rm(m_readLock, std::defer_lock); - if (!rm.try_lock()) - return false; - if (m_readCount > 0) - return false; - if (exclusive) - if (!m_writeLock.try_lock()) + if (m_multi) { + if (!rm.try_lock()) return false; + if (m_readCount > 0) + return false; + if (exclusive) + if (!m_writeLock.try_lock()) + return false; + } m_writeCount++; return true; } void releaseRead() { - std::unique_lock rm(m_readLock); - m_readCount--; - if (m_notify) + std::unique_lock rm(m_readLock, std::defer_lock); + if (m_multi) { + rm.lock(); m_cv.notify_all(); + } + m_readCount--; } void releaseWrite(bool exclusive = true) { - std::unique_lock rm(m_readLock); + std::unique_lock rm(m_readLock, std::defer_lock); serverAssert(m_writeCount > 0); - if (exclusive) - m_writeLock.unlock(); - m_writeCount--; - if (m_notify) + if (m_multi) { + rm.lock(); + if (exclusive) + m_writeLock.unlock(); m_cv.notify_all(); + } + m_writeCount--; } void downgradeWrite(bool exclusive = true) { @@ -85,8 +99,8 @@ class readWriteLock { acquireRead(); } - void setNotify(bool notify) { - m_notify = notify; + void setMulti(bool multi) { + m_multi = multi; } bool hasReader() {