Практика использования std::unique_ptr std::call_once std::once_flag
От: xobotik Россия  
Дата: 19.11.15 15:15
Оценка:
Здравствуйте!
Подскажите пожалуйста, плохо ли использовать (и почему плохо) std::unique_ptr , std::call_once и std::once_flag в следующем контексте:
template<typename T>
class ResourceCreator {
private:
    std::unique_ptr<T> _resource;
    std::once_flag _initFlag;
public:
    void Init() {
        std::call_once(_initFlag, [&]() { _resource.reset(new T()); });
    }
    std::unique_ptr<T> &getResource() {
        return _resource;
    }
    ~ResourceCreator() {
        _resource.release();
    }
};

template<typename T>
class ResourceCreatorArgs {
private:
    std::unique_ptr<T> _resource;
    std::once_flag _initFlag;
public:
    template<typename... Args>
    void Init(Args... constructorArgs) {
        std::call_once(_initFlag, [&]() { _resource.reset(new T(std::forward<Args>(constructorArgs)...)); });
    }
    std::unique_ptr<T> &getResource() {
        return _resource;
    }
    ~ResourceCreatorArgs() {
        _resource.release();
    }
};

template<typename T> 
class ResourceCreatorAndOnceRun {
private:
    ResourceCreator<T> _creator;
    std::once_flag _onceRun;
public:
    void Init(std::function<void()> func) {
        _creator.Init();
        std::call_once(_onceRun, func);
    }
    std::unique_ptr<T> &getResource() {
        return _creator.getResource(); 
    }
};

template<typename T>
class ResourceCreatorArgsAndOnceRun {
private:
    ResourceCreatorArgs<T> _creator;
    std::once_flag _onceRun;
public:
    void Init(std::function<void()> func, Args... constructorArgs) {
        _creator.Init(constructorArgs...);
        std::call_once(_onceRun, func);
    }
    std::unique_ptr<T> &getResource() {
        return _creator.getResource(); 
    }
};


Сценарий использования этих велосипедов:
namespace {
    ResourceCreatorArgsAndOnceRun<Loger> _loger;
}

inline void initLogging() {
    std::string fileName = getLogFileName(); // имя файла содержит время старта программы
    _loger.InitAndRun([&]() { createLogFile(fileName); }, fileName);
}

#define TO_LOG(text) \
    _loger.getResource().get()->save(LogEntry(__FILE__, __PRETTY_FUNCTION__, __LINE__, (text)));


P.S. Если код не очень, скажите пожалуйста, где косяки =)
Заранее спасибо!
С уважением!
std::call_once std::once_flag std::unique_ptr
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.