feat(hash): add synchronized export table template

This commit is contained in:
fallenoak 2023-03-27 17:28:51 -05:00 committed by GitHub
parent a0af28c9b0
commit 3d14119536
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 0 deletions

View file

@ -3,6 +3,7 @@
#include "storm/hash/Hashkey.hpp"
#include "storm/hash/TSExportTableSimpleReuse.hpp"
#include "storm/hash/TSExportTableSyncReuse.hpp"
#include "storm/hash/TSHashObject.hpp"
#include "storm/hash/TSHashTable.hpp"
#include "storm/hash/TSHashTableReuse.hpp"

View file

@ -0,0 +1,87 @@
#ifndef STORM_HASH_TS_EXPORT_TABLE_SYNC_REUSE_HPP
#define STORM_HASH_TS_EXPORT_TABLE_SYNC_REUSE_HPP
#include "storm/hash/Hashkey.hpp"
#include "storm/hash/TSExportTableSimpleReuse.hpp"
template <class T, class THandle, class TLockedHandle, class TSync>
class TSExportTableSyncReuse : public TSExportTableSimpleReuse<T, THandle> {
public:
// Virtual member functions
virtual ~TSExportTableSyncReuse() = default;
// Member functions
void Delete(THandle handle);
void DeleteUnlock(T* ptr, TLockedHandle lockedHandle);
T* Lock(THandle handle, TLockedHandle* lockedHandlePtr, int32_t forWriting);
T* NewLock(THandle* handlePtr, TLockedHandle* lockedHandlePtr);
void Unlock(TLockedHandle lockedHandle);
private:
// Member variables
TSync m_sync;
// Member functions
int32_t IsForWriting(TLockedHandle lockedHandle);
void SyncEnterLock(TLockedHandle* lockedHandlePtr, int32_t forWriting);
void SyncLeaveLock(TLockedHandle lockedHandle);
};
template <class T, class THandle, class TLockedHandle, class TSync>
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::Delete(THandle handle) {
TLockedHandle lockedHandle;
auto ptr = this->Lock(handle, &lockedHandle, 1);
this->DeleteUnlock(ptr, lockedHandle);
}
template <class T, class THandle, class TLockedHandle, class TSync>
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::DeleteUnlock(T* ptr, TLockedHandle lockedHandle) {
this->TSExportTableSimpleReuse<T, THandle>::Delete(ptr);
this->Unlock(lockedHandle);
}
template <class T, class THandle, class TLockedHandle, class TSync>
int32_t TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::IsForWriting(TLockedHandle lockedHandle) {
return reinterpret_cast<intptr_t>(lockedHandle) == 1;
}
template <class T, class THandle, class TLockedHandle, class TSync>
T* TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::Lock(THandle handle, TLockedHandle* lockedHandlePtr, int32_t forWriting) {
this->SyncEnterLock(lockedHandlePtr, forWriting);
auto ptr = this->Ptr(handle);
if (!ptr) {
this->SyncLeaveLock(*lockedHandlePtr);
*lockedHandlePtr = nullptr;
return nullptr;
}
return ptr;
}
template <class T, class THandle, class TLockedHandle, class TSync>
T* TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::NewLock(THandle* handlePtr, TLockedHandle* lockedHandlePtr) {
this->SyncEnterLock(lockedHandlePtr, 1);
return this->New(handlePtr);
}
template <class T, class THandle, class TLockedHandle, class TSync>
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::SyncEnterLock(TLockedHandle* lockedHandlePtr, int32_t forWriting) {
this->m_sync.Enter(forWriting);
*lockedHandlePtr = reinterpret_cast<TLockedHandle>(forWriting ? 1 : -1);
}
template <class T, class THandle, class TLockedHandle, class TSync>
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::SyncLeaveLock(TLockedHandle lockedHandle) {
if (lockedHandle) {
this->m_sync.Leave(this->IsForWriting(lockedHandle));
}
}
template <class T, class THandle, class TLockedHandle, class TSync>
void TSExportTableSyncReuse<T, THandle, TLockedHandle, TSync>::Unlock(TLockedHandle lockedHandle) {
this->SyncLeaveLock(lockedHandle);
}
#endif

View file

@ -1,4 +1,5 @@
#include "storm/Hash.hpp"
#include "storm/Thread.hpp"
#include "test/Test.hpp"
struct TestHashObject : TSHashObject<TestHashObject, HASHKEY_STRI> {
@ -11,6 +12,8 @@ struct TestExportObject : TSHashObject<TestHashObject, HASHKEY_NONE> {
typedef void* TestExportObjectHandle;
typedef void* TestExportLockedHandle;
TEST_CASE("TSHashTable", "[hash]") {
SECTION("constructs correctly") {
TSHashTable<TestHashObject, HASHKEY_STRI> hashTable;
@ -117,3 +120,44 @@ TEST_CASE("TSExportTableSimpleReuse::Delete", "[hash]") {
REQUIRE(exportTable.Ptr(handle) == nullptr);
}
}
TEST_CASE("TSExportTableSyncReuse", "[hash]") {
SECTION("constructs correctly") {
TSExportTableSyncReuse<TestExportObject, TestExportObjectHandle, TestExportLockedHandle, CCritSect> exportTable;
REQUIRE(exportTable.Head() == nullptr);
}
}
TEST_CASE("TSExportTableSyncReuse::NewLock", "[hash]") {
SECTION("returns a new object, handle, and locked handle") {
TSExportTableSyncReuse<TestExportObject, TestExportObjectHandle, TestExportLockedHandle, CCritSect> exportTable;
TestExportObjectHandle handle;
TestExportLockedHandle lockedHandle;
auto object = exportTable.NewLock(&handle, &lockedHandle);
exportTable.Unlock(lockedHandle);
REQUIRE(handle != nullptr);
REQUIRE(lockedHandle != nullptr);
REQUIRE(object != nullptr);
REQUIRE(object != handle);
REQUIRE(exportTable.Head() == object);
REQUIRE(exportTable.Ptr(handle) == object);
}
}
TEST_CASE("TSExportTableSyncReuse::Delete", "[hash]") {
SECTION("deletes object from export table") {
TSExportTableSyncReuse<TestExportObject, TestExportObjectHandle, TestExportLockedHandle, CCritSect> exportTable;
TestExportObjectHandle handle;
TestExportLockedHandle lockedHandle;
auto object = exportTable.NewLock(&handle, &lockedHandle);
exportTable.Unlock(lockedHandle);
exportTable.Delete(handle);
REQUIRE(handle != nullptr);
REQUIRE(object != nullptr);
REQUIRE(object != handle);
REQUIRE(exportTable.Head() == nullptr);
REQUIRE(exportTable.Ptr(handle) == nullptr);
}
}