/* * TPoolObject.hpp * * Created on: 24 авг. 2016 г. * Author: user */ #ifndef SOURCE_COMMON_POOLOBJECT_HPP_ #define SOURCE_COMMON_TPOOLOBJECT_HPP_ //! Шаблонный класс с реализацие логики работы с пулом объектов /**! * \tparam T тип, хранимый в пуле * \tparam size размер пула */ template class PoolObject { public: //! функция запроса ресурса из пула /* Запрос от внешних модулей. В случае, если ресурс * уже был запрошен, повторно не предоставляется (возвращается нулевой указатель). * \param [in] id идентификатор ресурса * \return указатель на ресурс или nullptr в случае недоступности ресурса */ T * grabObject(M id); //! Функция освобождения ресурса /* Запрос от внешних модулей. Ресурс освобождается для возможности * его дальнейшего использования. * TODO: в текущей реализации есть возможность последующего использования ресурса * по указателю, что может повредить другому запрашивающему этот ресурс модулю. * Подумать над возможным решением этой проблемы (Proxy?) * \param [in] resource указатель на освобождаемый ресурс */ void freeObject(T * & resource); //! Конструктор по умолчанию PoolObject() {} //! Деструктор по умолчанию virtual ~PoolObject() {} protected: //! Функция создания ресурса /* Виртуальная функция, делегирующая создание ресурса дочернему классу, реализующему * работу с пулом ресурсов конкретного типа. * \param [in] id идентификатор ресурса */ virtual T * createObject(M id) = 0; T * getObjectPtr(M id); void makeFree(M id); private: struct TRecord { T * pObject; bool isUse; TRecord() : pObject(0), isUse(false) {} }; TRecord pool[size]; }; template inline T * PoolObject::grabObject(M id) { unsigned int n_id = static_cast(id); if(n_id > size) return nullptr; if(!pool[n_id].isUse) { if(!pool[n_id].pObject) pool[n_id].pObject = createObject(id); pool[n_id].isUse = true; return pool[n_id].pObject; } else { return nullptr; } } template inline void PoolObject::freeObject(T * & resource) { for (int i = 0; i < size; i++){ if (pool[i].pObject == resource){ pool[i].isUse = false; break; } } resource = nullptr; } template inline T * PoolObject::getObjectPtr(M id) { unsigned int n_id = static_cast(id); if(n_id < size && pool[n_id].isUse) return pool[n_id].pObject; else return 0; } template inline void PoolObject::makeFree(M id) { unsigned int n_id = static_cast(id); pool[n_id].isUse = false; } #endif /* SOURCE_COMMON_POOLOBJECT_HPP_ */