From ba55476567b522e987337995f87a1055c3f901e5 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 1 Jan 2023 15:47:52 -0600 Subject: [PATCH] feat(instance): add TInstanceId and TSingletonInstanceId --- common/Instance.hpp | 7 ++ common/instance/TInstanceId.hpp | 14 +++ common/instance/TInstanceIdTable.hpp | 145 +++++++++++++++++++++++ common/instance/TSingletonInstanceId.hpp | 14 +++ 4 files changed, 180 insertions(+) create mode 100644 common/Instance.hpp create mode 100644 common/instance/TInstanceId.hpp create mode 100644 common/instance/TInstanceIdTable.hpp create mode 100644 common/instance/TSingletonInstanceId.hpp diff --git a/common/Instance.hpp b/common/Instance.hpp new file mode 100644 index 0000000..e1a101a --- /dev/null +++ b/common/Instance.hpp @@ -0,0 +1,7 @@ +#ifndef COMMON_INSTANCE_HPP +#define COMMON_INSTANCE_HPP + +#include "common/instance/TInstanceId.hpp" +#include "common/instance/TSingletonInstanceId.hpp" + +#endif diff --git a/common/instance/TInstanceId.hpp b/common/instance/TInstanceId.hpp new file mode 100644 index 0000000..e4562b3 --- /dev/null +++ b/common/instance/TInstanceId.hpp @@ -0,0 +1,14 @@ +#ifndef COMMON_INSTANCE_T_INSTANCE_ID_HPP +#define COMMON_INSTANCE_T_INSTANCE_ID_HPP + +#include +#include + +template +class TInstanceId : public TSLinkedNode { + public: + // Member variables + uint32_t m_id; +}; + +#endif diff --git a/common/instance/TInstanceIdTable.hpp b/common/instance/TInstanceIdTable.hpp new file mode 100644 index 0000000..815de60 --- /dev/null +++ b/common/instance/TInstanceIdTable.hpp @@ -0,0 +1,145 @@ +#ifndef COMMON_INSTANCE_T_INSTANCE_ID_TABLE_HPP +#define COMMON_INSTANCE_T_INSTANCE_ID_TABLE_HPP + +#include +#include +#include + +#define INSTANCE_TABLE_SLOT_COUNT 8 + +template +class TInstanceIdTable { + public: + // Types + class Iterator { + public: + TInstanceIdTable* m_table; + int32_t m_slot; + T* m_next; + }; + + // Member variables + SCritSect m_idCritsect; + uint32_t m_id; + int32_t m_idWrapped; + CSRWLock m_idLock[INSTANCE_TABLE_SLOT_COUNT]; + TSList> m_idList[INSTANCE_TABLE_SLOT_COUNT]; + + // Member functions + void Insert(T* instance); + T* Ptr(uint32_t id, int32_t lockMode, int32_t* findMask); + void Unlock(uint32_t slot, int32_t lockMode); + + private: + uint32_t NextId(); +}; + +template +void TInstanceIdTable::Insert(T* instance) { + if (instance->m_id) { + return; + } + + this->m_idCritsect.Enter(); + + auto id = this->NextId(); + + instance->m_id = id; + + uint32_t slot = id & (INSTANCE_TABLE_SLOT_COUNT - 1); + + auto idLock = &this->m_idLock[slot]; + + idLock->Enter(1); + + this->m_idList[slot].LinkNode(instance, 2, nullptr); + + idLock->Leave(1); + + this->m_idCritsect.Leave(); +} + +template +uint32_t TInstanceIdTable::NextId() { + uint32_t id; + int32_t exists; + + do { + while (1) { + id = this->m_id + 1; + + this->m_id++; + + if (this->m_id != 0) { + break; + } + + this->m_idWrapped = 1; + } + + if (this->m_idWrapped == 0) { + break; + } + + uint32_t slot = id & (INSTANCE_TABLE_SLOT_COUNT - 1); + + auto idLock = &this->m_idLock[slot]; + + idLock->Enter(0); + + exists = 0; + + auto idList = &this->m_idList[slot]; + + auto node = idList->Head(); + + while (node) { + if (node->m_id == id) { + exists = 1; + break; + } + + node = idList->Link(node)->Next(); + } + + idLock->Leave(0); + } while (exists); + + return id; +} + +template +T* TInstanceIdTable::Ptr(uint32_t id, int32_t lockMode, int32_t* findMask) { + if (id) { + uint32_t slot = id & (INSTANCE_TABLE_SLOT_COUNT - 1); + + auto idLock = &this->m_idLock[slot]; + + idLock->Enter(lockMode); + + auto idList = &this->m_idList[slot]; + + auto node = idList->Head(); + + while (node) { + if (node->m_id == id) { + *findMask = slot + (lockMode != 0 ? INSTANCE_TABLE_SLOT_COUNT : 0); + return node; + } + + node = idList->Link(node)->Next(); + } + + idLock->Leave(lockMode); + } + + *findMask = -1; + return nullptr; +} + +template +void TInstanceIdTable::Unlock(uint32_t slot, int32_t lockMode) { + this->m_idLock[slot].Leave(lockMode); +} + +#endif diff --git a/common/instance/TSingletonInstanceId.hpp b/common/instance/TSingletonInstanceId.hpp new file mode 100644 index 0000000..1aef572 --- /dev/null +++ b/common/instance/TSingletonInstanceId.hpp @@ -0,0 +1,14 @@ +#ifndef COMMON_INSTANCE_T_SINGLETON_INSTANCE_ID_HPP +#define COMMON_INSTANCE_T_SINGLETON_INSTANCE_ID_HPP + +#include "common/instance/TInstanceId.hpp" +#include "common/instance/TInstanceIdTable.hpp" + +template +class TSingletonInstanceId : public TInstanceId { + public: + // Static variables + static TInstanceIdTable s_idTable; +}; + +#endif