mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 11:12:29 +00:00
feat(instance): add TInstanceId and TSingletonInstanceId
This commit is contained in:
parent
689916d9c6
commit
ba55476567
4 changed files with 180 additions and 0 deletions
7
common/Instance.hpp
Normal file
7
common/Instance.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef COMMON_INSTANCE_HPP
|
||||||
|
#define COMMON_INSTANCE_HPP
|
||||||
|
|
||||||
|
#include "common/instance/TInstanceId.hpp"
|
||||||
|
#include "common/instance/TSingletonInstanceId.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
14
common/instance/TInstanceId.hpp
Normal file
14
common/instance/TInstanceId.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef COMMON_INSTANCE_T_INSTANCE_ID_HPP
|
||||||
|
#define COMMON_INSTANCE_T_INSTANCE_ID_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class TInstanceId : public TSLinkedNode<T> {
|
||||||
|
public:
|
||||||
|
// Member variables
|
||||||
|
uint32_t m_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
145
common/instance/TInstanceIdTable.hpp
Normal file
145
common/instance/TInstanceIdTable.hpp
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#ifndef COMMON_INSTANCE_T_INSTANCE_ID_TABLE_HPP
|
||||||
|
#define COMMON_INSTANCE_T_INSTANCE_ID_TABLE_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <storm/List.hpp>
|
||||||
|
#include <storm/Thread.hpp>
|
||||||
|
|
||||||
|
#define INSTANCE_TABLE_SLOT_COUNT 8
|
||||||
|
|
||||||
|
template <class T, size_t offset>
|
||||||
|
class TInstanceIdTable {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
TInstanceIdTable<T, offset>* 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<T, TSGetLink<T>> 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 <class T, size_t offset>
|
||||||
|
void TInstanceIdTable<T, offset>::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 <class T, size_t offset>
|
||||||
|
uint32_t TInstanceIdTable<T, offset>::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 <class T, size_t offset>
|
||||||
|
T* TInstanceIdTable<T, offset>::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 <class T, size_t offset>
|
||||||
|
void TInstanceIdTable<T, offset>::Unlock(uint32_t slot, int32_t lockMode) {
|
||||||
|
this->m_idLock[slot].Leave(lockMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
14
common/instance/TSingletonInstanceId.hpp
Normal file
14
common/instance/TSingletonInstanceId.hpp
Normal file
|
|
@ -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 T, size_t offset>
|
||||||
|
class TSingletonInstanceId : public TInstanceId<T> {
|
||||||
|
public:
|
||||||
|
// Static variables
|
||||||
|
static TInstanceIdTable<T, offset> s_idTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue