// . { ha::scoped_resource<void*, size_t> mem(::malloc, 1, ::free); ::memset(mem, 65, 1); }
// . { ha::scoped_resource<int> fd( [&filename]() { return ::open(filename.c_str(), O_RDONLY); }, ::close); assert(fd != -1); std::vector<char> buff(1024); ssize_t rc = ::read(fd, &buff[0], 1024); }
throw std::exception()
. { ha::scoped_resource<int, char*, int> fd(::open, filename.c_str(), O_RDONLY, ::close); if (fd == -1) throw std::runtime_error(std::string("open() failed: ") + ::strerror(errno)); std::vector<char> buff(1024); ssize_t rc = ::read(fd, &buff[0], 1024); }
std::functions
: initializer_t finalizer_t
. { ha::scoped_resource <resource_t, param1_t, ...> resource (ititializer, param1, ..., finalizer); resource_t plain_resource = resource.operator resource_t(); }
operator resource_t()
. It also allows you to create named initializers, thereby reusing them.std::initializer_list
.std::shared_ptr(T* ptr, deleter d)
. ha::scoped_resource<ffmpeg::AVFormatContext*> formatctx (ffmpeg::avformat_alloc_context, ffmpeg::avformat_free_context);
std::shared_ptr<ffmpeg::AVFormatContext> formatctx = std::shared_ptr<ffmpeg::AVFormatContext> (ffmpeg::avformat_alloc_context(), ffmpeg::avformat_free_context);
ha::scoped_resource<ffmpeg::AVCodecContext*> codecctx( ffmpeg::avcodec_alloc_context, [](ffmpeg::AVCodecContext* c) { ffmpeg::avcodec_close(c), ffmpeg::av_free(c); });
ha::scoped_resource<ffmpeg::AVCodec*, ffmpeg::AVCodecID> codec( ffmpeg::avcodec_find_decoder, codecctx->codec_id, [](__attribute__((unused)) ffmpeg::AVCodec* c) { });
ha::scoped_resource<ffmpeg::AVFrame*> frame(ffmpeg::avcodec_alloc_frame, ffmpeg::av_free);
std::shared_ptr<ffmpeg::AVFrame> frame = std::shared_ptr<ffmpeg::AVFrame>(ffmpeg::avcodec_alloc_frame(), ffmpeg::av_free);
ha::mutex mutex; ha::scoped_resource<ha::mutex*, ha::mutex*> scoped_lock( [](ha::mutex* m) -> ha::mutex* { return m->lock(), m; }, &mutex, [](ha::mutex* m) -> void { m->unlock(); } );
scoped_resource::scoped_resource(initializer_t, finalizer_t);
and then build up the variadic-part for the parameters. template <typename T, typename... A> class scoped_resource { public: typedef std::function<T (A...)> initializer_t; typedef std::function<void(T)> finalizer_t; typedef T resource_t; scoped_resource(initializer_t finit, A... args, finalizer_t final) : finit_(finit), final_(final), resource_(finit_(args...)) { }; ~scoped_resource() { final_(resource_); } template <typename Y> Y get() const { return static_cast<Y>(resource_); } T get() const { return resource_; } operator T() const { return get(); } // No copy, no move scoped_resource(const scoped_resource&) = delete; scoped_resource(scoped_resource&&) = delete; scoped_resource& operator=(const scoped_resource&) = delete; scoped_resource& operator=(scoped_resource&&) = delete; private: const initializer_t finit_; const finalizer_t final_; T resource_; };
Source: https://habr.com/ru/post/172817/
All Articles