Skip to content

Commit

Permalink
feat(kvssd): add ReadersWriterLock class to manage read and write locks
Browse files Browse the repository at this point in the history
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
easter423 committed Dec 6, 2024
1 parent c168f0b commit 2e3b1b8
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
130 changes: 130 additions & 0 deletions kvssd/ReadersWriterLock.h
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
11 changes: 11 additions & 0 deletions kvssd/kvssd_hashmap_db.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ Hashmap_KVSSD::~Hashmap_KVSSD()
// API 함수 4가지
kvs_result Hashmap_KVSSD::Read(const kvs_key &key, kvs_value &value_out)
{
rwl.lock_read();
auto it = db.find(key);
rwl.unlock_read();
if (it == db.end())
{
return KVS_ERR_KS_NOT_EXIST;
Expand All @@ -54,33 +56,42 @@ kvs_result Hashmap_KVSSD::Read(const kvs_key &key, kvs_value &value_out)

kvs_result Hashmap_KVSSD::Insert(const kvs_key &key, const kvs_value &value)
{
rwl.lock_write();
auto it = db.find(key);
if (it != db.end())
{
rwl.unlock_write();
return KVS_ERR_KS_EXIST;
}
db.insert({key, value});
rwl.unlock_write();
return KVS_SUCCESS;
}

kvs_result Hashmap_KVSSD::Update(const kvs_key &key, const kvs_value &value)
{
rwl.lock_write();
auto it = db.find(key);
if (it == db.end())
{
rwl.unlock_write();
return KVS_ERR_KS_NOT_EXIST;
}
it->second = value;
rwl.unlock_write();
return KVS_SUCCESS;
}

kvs_result Hashmap_KVSSD::Delete(const kvs_key &key)
{
rwl.lock_write();
auto it = db.find(key);
if (it == db.end())
{
rwl.unlock_write();
return KVS_ERR_KS_NOT_EXIST;
}
db.erase(key);
rwl.unlock_write();
return KVS_SUCCESS;
}
2 changes: 2 additions & 0 deletions kvssd/kvssd_hashmap_db.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef YCSB_C_KVSSD_HASHMAP_DB_H_
#define YCSB_C_KVSSD_HASHMAP_DB_H_

#include "ReadersWriterLock.h"
#include <cstring>
#include <cstdint>
#include <unordered_map>
Expand Down Expand Up @@ -102,6 +103,7 @@ class Hashmap_KVSSD : public KVSSD

private:
std::unordered_map<kvs_key, kvs_value> db;
ReadersWriterLock rwl;
};

#endif // YCSB_C_KVSSD_HASHMAP_DB_H_

0 comments on commit 2e3b1b8

Please sign in to comment.