#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ #define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ #include "../storagemanager/StorageManagerIF.h" #include /** * The Placement Factory is used to create objects at runtime in a specific pool. * In general, this should be avoided and it should only be used if you know what you are doing. * You are not allowed to use this container with a type that allocates memory internally like ArrayList. * * Also, you have to check the returned pointer in generate against nullptr! * * A backend of Type StorageManagerIF must be given as a place to store the new objects. * Therefore ThreadSafety is only provided by your StorageManager Implementation. * * Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared. * * The concept is based on the placement new operator. * * @warning Do not use with any Type that allocates memory internally! * @ingroup container */ class PlacementFactory { public: PlacementFactory(StorageManagerIF* backend) : dataBackend(backend) { } /*** * Generates an object of type T in the backend storage. * * @warning Do not use with any Type that allocates memory internally! * * @tparam T Type of Object * @param args Constructor Arguments to be passed * @return A pointer to the new object or a nullptr in case of failure */ template T* generate(Args&&... args) { store_address_t tempId; uint8_t* pData = nullptr; ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), &pData); if (result != HasReturnvaluesIF::RETURN_OK) { return nullptr; } T* temp = new (pData) T(std::forward(args)...); return temp; } /*** * Function to destroy the object allocated with generate and free space in backend. * This must be called by the user. * * @param thisElement Element to be destroyed * @return RETURN_OK if the element was destroyed, different errors on failure */ template ReturnValue_t destroy(T* thisElement) { if (thisElement == nullptr){ return HasReturnvaluesIF::RETURN_FAILED; } //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). thisElement->~T(); uint8_t* pointer = (uint8_t*) (thisElement); return dataBackend->deleteData(pointer, sizeof(T)); } private: StorageManagerIF* dataBackend; }; #endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */