#include <functional>
#include <vector>
#include <memory>
#include <mutex>
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
class ResourceManager{
public:
using Actions = struct{
using LoadFunc = std::function<T*(const std::string &)>;
using UnloadFunc = std::function<void(T *)>;
LoadFunc load;
UnloadFunc unload;
};
using ResourcePtr = std::unique_ptr<T, typename Actions::UnloadFunc>;
struct MutexWrapper{
std::mutex m;
MutexWrapper() {}
MutexWrapper(MutexWrapper const&) {}
MutexWrapper& operator=(MutexWrapper const&) { return *this; }
inline std::mutex &get(){ return m; }
};
using Key = size_t;
public:
ResourceManager(Actions actions):
_actions(actions){}
ResourceManager(const ResourceManager &rhs) = delete;
public:
Key load(const std::string &path){
auto resource = _actions.load(path);
return load(resource);
}
Key load(T *resource){
std::lock_guard<std::mutex> guard(_mutex);
auto resourcePtr = ResourcePtr(resource, _actions.unload);
_resources.push_back(std::move(resourcePtr));
_mutexes.push_back(MutexWrapper());
return _resources.size()-1;
}
void unload(Key key){
std::lock_guard<std::mutex> guard(_mutex);
_resources.erase(_resources.begin()+key);
_mutexes.erase(_mutexes.begin()+key);
}
void operate(Key key, std::function<void(T&)> operation){
std::lock_guard<std::mutex> guard(_mutexes.at(key).get());
operation(*_resources.at(key));
}
void operate(Key key, std::function<void(const T&)> operation) const{
std::lock_guard<std::mutex> guard(_mutexes.at(key).get());
operation(*_resources.at(key));
}
private:
Actions _actions;
std::vector<ResourcePtr> _resources;
std::vector<MutexWrapper> _mutexes;
std::mutex _mutex;
};
int main() {
ResourceManager<int> rm{{
[](const std::string &){return new int;},
[](int *arg){ delete arg; }
}};
auto id = rm.load(new int(5));
rm.operate(id, [](int&arg){ cout << "Hello world! " << arg << endl; });
return 0;
}