RAII + C ++ рд╡реИрд░реЗрдбрд┐рдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ = рдЬреАрдд

рдореИрдВрдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ C ++ Variadic Templates рдХреЛ рдирд┐рдХрдЯ рд╕реЗ рджреЗрдЦрд╛ рдФрд░ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ рдирдП RAII рд╕реНрдХреЛрдкреНрдб рд░рд┐рд╕реЛрд░реНрд╕ рдореИрдиреЗрдЬрд░ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛ред
рдпрд╣ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдирд┐рдХрд▓рд╛ред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, C- рд╢реИрд▓реА рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрди рдХреЗ рд╕рд╛рде:
//    . { 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(); } 


рд╕рдВрд╕рд╛рдзрди рд░реИрдкрд░ рдХреЗ рдЕрдиреНрдп рдЖрд░рдПрдЖрдИ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдХреНрдпрд╛ рд▓рд╛рдн рд╣реИ?

  1. рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдореЗрдВ рдХрдореА рдХреЗ рджреМрд░рд╛рди рдЗрдирд┐рд╢рд▓рд╛рдЗрдЬрд╝рд░ рдХреЛ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рд╣реАред рдпрд╣, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ "рд╕рд╛рдорд╛рдиреНрдп" рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдЯреНрд░рд╛рдВрд╕рдлрд╝рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ operator resource_t() рд▓рд┐рдП рдкрд╣рд▓реА рдХреЙрд▓ рд╕реЗ рдкрд╣рд▓реЗ рдЖрд▓рд╕реА-рд╢реИрд▓реА рдореЗрдВ рдПрдХ рд╕рдВрд╕рд╛рдзрди рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдирд╛рдорд╛рдВрдХрд┐рдд рдирд╛рдорд╛рдВрдХрд┐рдд рдмрдирд╛рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЙрдирдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  2. рдЖрдк рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ, рд╢рд╛рдпрдж, рдПрдХ рдФрд░ рджреВрд╕рд░рд╛ рдЙрдкрдпреЛрдЧреА рддрдВрддреНрд░ рд╣реИ - std::initializer_list ред
  3. рдпрджрд┐ рдмрд┐рдВрджреБ 2. рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдПрдХ рд▓реИрдореНрдмрдбрд╛ рдХреЛ рдПрдХ рдЗрдирд┐рд╢рд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рд╕рднреА рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИред
  4. рдбрд┐рдирд╛рдпрдЯрд┐рд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рдкрд╛рд╕ рдПрдХ рдПрдХрд▓ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ - рд╕рдВрд╕рд╛рдзрди рдХрд╛ рдкреНрд░рдХрд╛рд░, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдпрд╣ рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдбрд┐рдирд╛рдЗрдирд┐рдЯрд╛рдЗрдЬреЗрд╢рди рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рд▓реЙрдХ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
  5. рдЗрд╕реЗ std::shared_ptr(T* ptr, deleter d) рд╕реЗ рдЕрдзрд┐рдХ рдЖрд╕рд╛рдиреА рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ std::shared_ptr(T* ptr, deleter d) ред


рдиреБрдХрд╕рд╛рди?
рдХрднреА-рдХрднреА рдкреВрд░реНрдг рд╕рдВрд╕рд╛рдзрди рдЖрд╡рд░рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЕрднреА рднреА рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рд╣реИред

рдФрд░ рдЙрджрд╛рд╣рд░рдг рдЪрд╛рд╣рд┐рдП? рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ:

рдПрдХ AVFormatContext рд╕рдВрджрд░реНрдн рдмрдирд╛рдирд╛:
 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); 


рдпрд╛ рдлрд┐рд░, рдПрдХ рд╕рдореНрдорд┐рд╢реНрд░ deinitializer рдпрд╣рд╛рдБ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
 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); 

рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирдЧреНрди рд╕рд╛рджреЗ-рд╕реА рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ? рдФрд░ рдорд╛рдиреНрдп C ++ рд╡рд╛рд▓реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╣рд╛рдВ рд╣реИрдВ?
рдФрд░ рдпрд╣рд╛рдБ:
 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::scoped_resource(initializer_t, finalizer_t); рдХреА рдШреЛрд╖рдгрд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ scoped_resource::scoped_resource(initializer_t, finalizer_t); рдФрд░ рдлрд┐рд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рд╡реИрд░реЗрдбрд┐рдХ рднрд╛рдЧ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВред

рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡реИрд╕реЗ рднреА рдХрд╣рд╛рдБ рд╣реИ, рд╣реБрд╣?
 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/In172817/


All Articles