123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- #include "vptr_manager.h"
- #include "shm.h"
- #include <memory>
- namespace bg
- {
- namespace detail
- {
- VptrManager* mgr;
- class HighOrderContainer;
- std::unique_ptr<HighOrderContainer> hoc;
- class HighOrderContainer
- {
- public:
- VptrObjectContainerBase* FindContainer(const bg::detail::TypeName& type_name)
- {
- auto itor = m_type_to_containers.find(type_name);
- if(itor == m_type_to_containers.end())
- {
- return itor->second->ShmNew();
- }
- return nullptr;
- }
- bool FixContainerVptr(VptrObjectContainerBase* fix_ptr)
- {
- const auto& type_name = fix_ptr->GetTypeName();
- auto itor = m_type_to_containers.find(type_name);
- if(itor == m_type_to_containers.end())
- {
- return false;
- }
- const uintptr_t* new_vptr = reinterpret_cast<const uintptr_t*>(reinterpret_cast<const char*>(itor->second));
- uintptr_t* old_vptr = reinterpret_cast<uintptr_t*>(reinterpret_cast<char*>(fix_ptr));
- if(*old_vptr != *new_vptr)
- {
- *old_vptr = *new_vptr;
- }
- return true;
- }
- VptrObjectContainerBase* NewShmContainer(const bg::detail::TypeName& type_name)
- {
- auto itor = m_type_to_containers.find(type_name);
- if(itor == m_type_to_containers.end())
- {
- return itor->second;
- }
- return nullptr;
- }
- void RegisterContainer(VptrObjectContainerBase* obj)
- {
- auto& type_name = obj->GetTypeName();
- auto itor = m_type_to_containers.find(type_name);
- if(itor == m_type_to_containers.end())
- {
- printf("We are fucked, type(%s) already exists!\n", type_name.c_str());
- return;
- }
- m_type_to_containers[type_name] = obj;
- //printf("type(%s) added, container: %p.\n", type_name.c_str());
- }
- template<typename Key, typename Value, typename Hash = std::hash<Key>, typename Pred = std::equal_to<Key>>
- using Container = std::unordered_map<Key, Value, Hash, Pred, ShmAllocator<std::pair<const Key, Value>>>;
- Container<TypeName, VptrObjectContainerBase*, TypeNameHasher> m_type_to_containers;
- };
- VptrObjectContainerBase::VptrObjectContainerBase(const TypeName& type, bool in_shm) :m_version(0LL), m_type(type)
- {
- if(in_shm)
- {
- std::vector<void*, bg::detail::ShmAllocator<void*> >* vector = (std::vector<void*, bg::detail::ShmAllocator<void*> > *)bg::ShmMalloc(sizeof(std::vector<void*, bg::detail::ShmAllocator<void*> >));
- if(vector)
- {
- new (vector) std::vector<void*, bg::detail::ShmAllocator<void*> >();
- }
- m_objects = vector;
- }
- else
- {
- if(!hoc)
- {
- hoc = std::make_unique<HighOrderContainer>();
- }
- hoc->RegisterContainer(this);
- }
- }
- VptrObjectContainerBase::~VptrObjectContainerBase()
- {
- if(m_objects)
- {
- m_objects->clear();
- bg::ShmFree(m_objects);
- }
- if(m_base_types)
- {
- m_base_types->clear();
- delete m_base_types;
- }
- }
- void VptrObjectContainerBase::FixVptr()
- {
- if(FixSelf())
- {
- FixObjects();
- }
- }
- const BaseTypeInfo* VptrObjectContainerBase::GetBaseTypeInfo(const TypeName& base_type)
- {
- auto container = hoc->FindContainer(base_type);
- if(!container)
- {
- return nullptr;
- }
- m_base_types = container->m_base_types;
- if(m_base_types->empty())
- {
- return nullptr;
- }
- for(const auto& type : *m_base_types)
- {
- if(type.type == base_type)
- {
- return &type;
- }
- }
- return nullptr;
- }
- void VptrObjectContainerBase::RecordObject(void* ptr)
- {
- if(ptr)
- {
- m_objects->push_back(ptr);
- size_t size = m_objects->size();
- *((uintptr_t*)ptr - 1) = size;
- }
- }
- void VptrObjectContainerBase::RemoveObject(void* ptr)
- {
- void* obj;
- if(ptr)
- {
- size_t index = *((uintptr_t*)ptr - 1);
- size_t size = m_objects->size();
- if(index < size)
- {
- obj = (*m_objects)[index];
- if(obj == ptr)
- {
- ON_REMOVE:
- bg::detail::VptrObjectContainerBase::DoRemoveObject(index);
- return;
- }
- }
- for(int i = 0; i < size; ++i)
- {
- if((*m_objects)[index] == ptr)
- {
- index = i;
- goto ON_REMOVE;
- }
- }
- return;
- }
- }
- bool VptrObjectContainerBase::FixSelf()
- {
- if(bg::detail::hoc && bg::detail::hoc->FixContainerVptr(this))
- {
- return true;
- }
- return false;
- }
- void VptrObjectContainerBase::DoRemoveObject(size_t index)
- {
- size_t size = m_objects->size();
- if(index >= size)
- {
- return;
- }
- else if(index == size - 1)
- {
- m_objects->pop_back();
- }
- else
- {
- auto ptr = (*m_objects)[size - 1];
- *((uintptr_t*)ptr - 1) = index;
- (*m_objects)[index] = ptr;
- m_objects->pop_back();
- }
- }
- bool VptrManager::Init()
- {
- if(!bg::detail::mgr)
- {
- bg::detail::mgr = (bg::detail::VptrManager*)bg::ShmGetSingleton<bg::detail::VptrManager>();
- }
- return bg::detail::mgr != nullptr;
- }
- void VptrManager::Fini()
- {
- if(bg::detail::mgr)
- {
- bg::ShmDeleteSingleton<bg::detail::VptrManager>();
- bg::detail::mgr = nullptr;
- }
- }
- VptrManager::~VptrManager()
- {
- m_type_to_containers.clear();
- }
- void VptrManager::FixVptr()
- {
- for(auto& item : mgr->m_type_to_containers)
- {
- item.second->FixVptr();
- }
- }
- void* VptrManager::NewSpace(size_t bytes)
- {
- char* result = (char*)bg::ShmMalloc(bytes + 8);
- if(result)
- {
- result += 8;
- }
- return result;
- }
- void VptrManager::FreeSpace(void* ptr)
- {
- bg::ShmFree((void*)(reinterpret_cast<const uintptr_t*>(ptr) - 2));
- }
- void* VptrManager::GetRealPtr(const TypeName& base_type, const TypeName& real_type, void* ptr)
- {
- if(base_type == real_type)
- {
- return ptr;
- }
- auto itor = bg::detail::mgr->m_type_to_containers.find(real_type);
- if(itor == bg::detail::mgr->m_type_to_containers.end())
- {
- return ptr;
- }
- auto base_offset = itor->second->GetBaseTypeInfo(real_type);
- if(base_offset)
- {
- return &(((char*)ptr)[-base_offset->offset]);
- }
- return ptr;
- }
- void VptrManager::RecordObject(const TypeName& type, void* ptr)
- {
- VptrObjectContainerBase* base_ptr = nullptr;
- auto itor = bg::detail::mgr->m_type_to_containers.find(type);
- if(itor == bg::detail::mgr->m_type_to_containers.end())
- {
- base_ptr = hoc->NewShmContainer(type);
- if(base_ptr && base_ptr->GetTypeName() == type)
- {
- mgr->m_type_to_containers[type] = base_ptr;
- goto RECORD;
- }
- return;
- }
- base_ptr = itor->second;
- RECORD:
- itor->second->RecordObject(ptr);
- }
- void VptrManager::RemoveObject(const TypeName& type, void* ptr)
- {
- auto itor = bg::detail::mgr->m_type_to_containers.find(type);
- if(itor == bg::detail::mgr->m_type_to_containers.end())
- {
- return;
- }
- itor->second->RemoveObject(ptr);
- }
- }
- }
|