forked from ls4154/YCSB-cpp
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(kvssd): add ReadersWriterLock class to manage read and write locks
feat(kvssd): add support for ReadersWriterLock in kvssd_hashmap_db.cc to improve concurrency feat(kvssd): add support for ReadersWriterLock in kvssd_hashmap_db.h to improve concurrency
- Loading branch information
Showing
3 changed files
with
143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#ifndef READERS_WRITER_LOCK_H | ||
#define READERS_WRITER_LOCK_H | ||
#include <atomic> | ||
#include <condition_variable> | ||
#include <mutex> | ||
#include <thread> | ||
|
||
class ReadersWriterLock | ||
{ | ||
std::atomic_int readRequests{0}; | ||
std::atomic_int writeRequests{0}; | ||
std::condition_variable cv; | ||
std::mutex m; | ||
std::mutex mw; | ||
void (ReadersWriterLock::*beforeRead)(){&ReadersWriterLock::before_read_msl}; | ||
void (ReadersWriterLock::*afterRead)(){&ReadersWriterLock::after_read_msl}; | ||
void (ReadersWriterLock::*beforeWrite)(){&ReadersWriterLock::before_write_msl}; | ||
void (ReadersWriterLock::*afterWrite)(){&ReadersWriterLock::after_write_msl}; | ||
|
||
inline void before_read_m2cv() | ||
{ | ||
this->readRequests++; | ||
if (this->writeRequests > 0) | ||
{ | ||
this->readRequests--; | ||
std::unique_lock<std::mutex> lk(this->m); | ||
this->cv.notify_all(); | ||
while (writeRequests > 0) | ||
this->cv.wait(lk); | ||
this->readRequests++; | ||
} | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void after_read_m2cv() | ||
{ | ||
this->readRequests--; | ||
this->cv.notify_all(); | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void before_write_m2cv() | ||
{ | ||
this->writeRequests++; | ||
std::unique_lock<std::mutex> lk(this->m); | ||
while (this->readRequests > 0) | ||
this->cv.wait(lk); | ||
this->mw.lock(); | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void after_write_m2cv() | ||
{ | ||
this->writeRequests--; | ||
this->cv.notify_all(); | ||
this->mw.unlock(); | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void before_read_msl() | ||
{ | ||
this->readRequests++; | ||
if (this->writeRequests > 0) | ||
{ | ||
this->readRequests--; | ||
std::unique_lock<std::mutex> lk(this->mw); | ||
this->readRequests++; | ||
lk.unlock(); | ||
} | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void after_read_msl() | ||
{ | ||
this->readRequests--; | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void before_write_msl() | ||
{ | ||
this->mw.lock(); | ||
this->writeRequests++; | ||
while (this->readRequests > 0) | ||
std::this_thread::yield(); | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void after_write_msl() | ||
{ | ||
this->writeRequests--; | ||
this->mw.unlock(); | ||
} | ||
//----------------------------------------------------------------------------- | ||
inline void empty_function() {} | ||
|
||
public: | ||
enum class LockStyle | ||
{ | ||
NONE, // No synchronization | ||
M2CV, // 2 mutexes and one conditional variable | ||
MSL // Mutex and spinlock | ||
}; | ||
//----------------------------------------------------------------------------- | ||
bool set_lock_style(LockStyle lockStyle) | ||
{ | ||
bool ret = true; | ||
if (lockStyle == LockStyle::MSL) | ||
{ | ||
this->beforeRead = &ReadersWriterLock::before_read_msl; | ||
this->afterRead = &ReadersWriterLock::after_read_msl; | ||
this->beforeWrite = &ReadersWriterLock::before_write_msl; | ||
this->afterWrite = &ReadersWriterLock::after_write_msl; | ||
} | ||
else if (lockStyle == LockStyle::M2CV) | ||
{ | ||
this->beforeRead = &ReadersWriterLock::before_read_m2cv; | ||
this->afterRead = &ReadersWriterLock::after_read_m2cv; | ||
this->beforeWrite = &ReadersWriterLock::before_write_m2cv; | ||
this->afterWrite = &ReadersWriterLock::after_write_m2cv; | ||
} | ||
else if (lockStyle == LockStyle::NONE) | ||
{ | ||
this->beforeRead = &ReadersWriterLock::empty_function; | ||
this->afterRead = &ReadersWriterLock::empty_function; | ||
this->beforeWrite = &ReadersWriterLock::empty_function; | ||
this->afterWrite = &ReadersWriterLock::empty_function; | ||
} | ||
else | ||
ret = false; | ||
return (ret); | ||
} | ||
inline void lock_read() { (this->*beforeRead)(); } | ||
inline void unlock_read() { (this->*afterRead)(); } | ||
inline void lock_write() { (this->*beforeWrite)(); } | ||
inline void unlock_write() { (this->*afterWrite)(); } | ||
}; | ||
#endif // READERS_WRITER_LOCK_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters