From e5eff5d76f98170d6b583aa19e9c6ebd58407eb4 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sat, 25 May 2019 11:15:26 +0300 Subject: [PATCH] genesys: Add facility for auto releasing static data on backend exit --- backend/genesys.cc | 2 ++ backend/genesys_low.cc | 19 +++++++++++++++++++ backend/genesys_low.h | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/backend/genesys.cc b/backend/genesys.cc index 5b04158b6..a688b0ed5 100644 --- a/backend/genesys.cc +++ b/backend/genesys.cc @@ -6453,6 +6453,8 @@ sane_exit_impl(void) sanei_usb_exit(); + run_functions_at_backend_exit(); + DBGCOMPLETED; } diff --git a/backend/genesys_low.cc b/backend/genesys_low.cc index e2b69eeb8..f5af01440 100644 --- a/backend/genesys_low.cc +++ b/backend/genesys_low.cc @@ -2329,3 +2329,22 @@ void sanei_gl_vector_destroy(Genesys_Vector* v) v->capacity = 0; v->element_size = 0; } + +static std::unique_ptr>> s_functions_run_at_backend_exit; + +void add_function_to_run_at_backend_exit(std::function function) +{ + if (!s_functions_run_at_backend_exit) + s_functions_run_at_backend_exit.reset(new std::vector>()); + s_functions_run_at_backend_exit->push_back(std::move(function)); +} + +void run_functions_at_backend_exit() +{ + for (auto it = s_functions_run_at_backend_exit->rbegin(); + it != s_functions_run_at_backend_exit->rend(); ++it) + { + (*it)(); + } + s_functions_run_at_backend_exit.release(); +} diff --git a/backend/genesys_low.h b/backend/genesys_low.h index f801c2b98..7da9efd2d 100644 --- a/backend/genesys_low.h +++ b/backend/genesys_low.h @@ -81,8 +81,12 @@ #include "../include/_stdint.h" +#include +#include +#include #include #include +#include #define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */ #define DBG_error 1 /* fatal errors */ @@ -1317,4 +1321,38 @@ inline void wrap_status_code_to_exception(SANE_Status status) throw SaneException(status); } +void add_function_to_run_at_backend_exit(std::function function); + +// calls functions added via add_function_to_run_at_backend_exit() in reverse order of being +// added. +void run_functions_at_backend_exit(); + +template +class StaticInit { +public: + StaticInit() = default; + StaticInit(const StaticInit&) = delete; + StaticInit& operator=(const StaticInit&) = delete; + + template + void init(Args&& ... args) + { + ptr_ = std::unique_ptr(new T(std::forward(args)...)); + add_function_to_run_at_backend_exit([this](){ deinit(); }); + } + + void deinit() + { + ptr_.release(); + } + + const T* operator->() const { return ptr_.get(); } + T* operator->() { return ptr_.get(); } + const T& operator*() const { return *ptr_.get(); } + T& operator*() { return *ptr_.get(); } + +private: + std::unique_ptr ptr_; +}; + #endif /* not GENESYS_LOW_H */