mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 03:02: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