147 lines
4.1 KiB
C++
147 lines
4.1 KiB
C++
/*!\file
|
||
* \brief Файл содержит модуль хранения и распостранения ресурсов программы.
|
||
*/
|
||
/*
|
||
* ResourceHolder.h
|
||
*
|
||
* Created on: 22 нояб. 2018 г.
|
||
* Author: titov
|
||
*/
|
||
|
||
#ifndef SOURCE_SYSTEMIC_RESOURCEHOLDER_H_
|
||
#define SOURCE_SYSTEMIC_RESOURCEHOLDER_H_
|
||
|
||
#include <stdint.h>
|
||
|
||
#include <cstddef>
|
||
#include <typeinfo>
|
||
#include <new>
|
||
#include <memory_resource>
|
||
#include <unordered_map>
|
||
#include <map>
|
||
|
||
#include "../memories/memories.hh"
|
||
#include "../memories/pmr/StaticMemoryResource.hh"
|
||
#include "../common/ResourceKeeper.hpp"
|
||
#include "../systemic/ResourceRecord.hpp"
|
||
|
||
namespace systemic {
|
||
|
||
class ResourceHolder {
|
||
public:
|
||
typedef ResourceRecord::Id Id;
|
||
typedef ResourceRecord::Tag Tag;
|
||
|
||
template<typename Type, Tag = 0>
|
||
void share( Type & obj, Id id );
|
||
|
||
template<typename Type, Tag = 0>
|
||
void insert( ResourceKeeper<Type> * rk, Id id );
|
||
|
||
template<typename Type, Tag = 0>
|
||
ResourceKeeper<Type> * getShared( Id id );
|
||
|
||
struct NotificationInterface {
|
||
virtual void notify( Id id, Tag tag, const std::type_info * type, void * rk ) = 0;
|
||
virtual ~NotificationInterface() = default;
|
||
};
|
||
|
||
static NotificationInterface & getDefault() {
|
||
struct DefaultHerald : public NotificationInterface {
|
||
void notify( Id id, Tag tag, const std::type_info * type, void * rk ) {}
|
||
};
|
||
|
||
static DefaultHerald herald;
|
||
return herald;
|
||
}
|
||
|
||
ResourceHolder( std::size_t max_size,
|
||
std::pmr::memory_resource * record_allocator,
|
||
std::pmr::memory_resource * record_guard_allocator = nullptr,
|
||
NotificationInterface & herald = getDefault() );
|
||
|
||
virtual void * getRecord( const std::type_info & obj_type, Id id, Tag tag );
|
||
|
||
private:
|
||
|
||
typedef std::map<
|
||
ResourceRecord::Info,
|
||
ResourceRecord::Data,
|
||
std::less< ResourceRecord::Info >,
|
||
std::pmr::polymorphic_allocator < std::pair< const ResourceRecord::Info, ResourceRecord::Data > >
|
||
> ResourceRecordMap;
|
||
|
||
const std::size_t size_limit;
|
||
ResourceRecordMap records;
|
||
NotificationInterface & herald;
|
||
|
||
std::pmr::memory_resource * record_allocator;
|
||
std::pmr::memory_resource * record_guard_allocator;
|
||
};
|
||
|
||
template<std::size_t num>
|
||
struct ResourceHolderBox {
|
||
ResourceRecord records[num];
|
||
ResourceHolder manager;
|
||
|
||
ResourceHolderBox( std::pmr::memory_resource* allocator )
|
||
: records(),
|
||
manager(num, allocator) {}
|
||
};
|
||
|
||
} /* namespace systemic */
|
||
|
||
template<typename Type, systemic::ResourceHolder::Tag tag>
|
||
void systemic::ResourceHolder::share( Type & obj, Id id ) {
|
||
|
||
//while( records.size() == size_limit );
|
||
|
||
const std::type_info & obj_type = typeid(Type);
|
||
ResourceRecord::Info record_info(&obj_type, id, tag);
|
||
|
||
ResourceRecordMap::iterator iter = records.find(record_info);
|
||
|
||
if( records.end() != iter ) return;
|
||
|
||
std::atomic_flag * record_guard =
|
||
memories::instance_object<std::atomic_flag>(*record_guard_allocator);
|
||
|
||
ResourceKeeper<Type> * record_keeper =
|
||
memories::instance_object< ResourceKeeper< Type > >(*record_allocator, obj, *record_guard);
|
||
|
||
void * record_data = reinterpret_cast< void * >(record_keeper);
|
||
|
||
records[record_info] = record_data;
|
||
|
||
herald.notify(id, tag, &obj_type, record_data);
|
||
}
|
||
|
||
template<typename Type, systemic::ResourceHolder::Tag tag>
|
||
ResourceKeeper<Type> * systemic::ResourceHolder::getShared( Id id ) {
|
||
|
||
const std::type_info & obj_type = typeid(Type);
|
||
|
||
void * record_data = getRecord(obj_type, id, tag);
|
||
|
||
return reinterpret_cast< ResourceKeeper<Type> * >(record_data);
|
||
|
||
}
|
||
|
||
template<typename Type, systemic::ResourceHolder::Tag tag>
|
||
void systemic::ResourceHolder::insert( ResourceKeeper<Type> * record_keeper, Id id ) {
|
||
|
||
//while( records.size() == size_limit );
|
||
|
||
const std::type_info & obj_type = typeid(Type);
|
||
ResourceRecord::Info record_info(&obj_type, id, tag);
|
||
|
||
ResourceRecordMap::iterator iter = records.find(record_info);
|
||
|
||
if( records.end() != iter ) return;
|
||
|
||
records[record_info] = reinterpret_cast< void * >(record_keeper);
|
||
|
||
}
|
||
|
||
#endif /* SOURCE_SYSTEMIC_RESOURCEHOLDER_HPP_ */
|