summaryrefslogtreecommitdiff
path: root/include/libcamera/base/bound_method.h
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@ideasonboard.com>2021-06-15 16:15:12 +0100
committerKieran Bingham <kieran.bingham@ideasonboard.com>2021-06-25 16:11:08 +0100
commit27aff949fbc1b9aabfc594bbfd6f94be55a086ec (patch)
tree9ddbc2462a685a6db3ed33f09ed7a493376439d6 /include/libcamera/base/bound_method.h
parent6410d1d37c1ea9d1d168840a7ba063facb0bc9d6 (diff)
libcamera/base: Move extended base functionality
Move the functionality for the following components to the new base support library: - BoundMethod - EventDispatcher - EventDispatcherPoll - Log - Message - Object - Signal - Semaphore - Thread - Timer While it would be preferable to see these split to move one component per commit, these components are all interdependent upon each other, which leaves us with one big change performing the move for all of them. Reviewed-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'include/libcamera/base/bound_method.h')
-rw-r--r--include/libcamera/base/bound_method.h239
1 files changed, 239 insertions, 0 deletions
diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h
new file mode 100644
index 00000000..282f9b58
--- /dev/null
+++ b/include/libcamera/base/bound_method.h
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * bound_method.h - Method bind and invocation
+ */
+#ifndef __LIBCAMERA_BASE_BOUND_METHOD_H__
+#define __LIBCAMERA_BASE_BOUND_METHOD_H__
+
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+namespace libcamera {
+
+class Object;
+
+enum ConnectionType {
+ ConnectionTypeAuto,
+ ConnectionTypeDirect,
+ ConnectionTypeQueued,
+ ConnectionTypeBlocking,
+};
+
+class BoundMethodPackBase
+{
+public:
+ virtual ~BoundMethodPackBase() = default;
+};
+
+template<typename R, typename... Args>
+class BoundMethodPack : public BoundMethodPackBase
+{
+public:
+ BoundMethodPack(const Args &... args)
+ : args_(args...)
+ {
+ }
+
+ std::tuple<typename std::remove_reference_t<Args>...> args_;
+ R ret_;
+};
+
+template<typename... Args>
+class BoundMethodPack<void, Args...> : public BoundMethodPackBase
+{
+public:
+ BoundMethodPack(const Args &... args)
+ : args_(args...)
+ {
+ }
+
+ std::tuple<typename std::remove_reference_t<Args>...> args_;
+};
+
+class BoundMethodBase
+{
+public:
+ BoundMethodBase(void *obj, Object *object, ConnectionType type)
+ : obj_(obj), object_(object), connectionType_(type)
+ {
+ }
+ virtual ~BoundMethodBase() = default;
+
+ template<typename T, typename std::enable_if_t<!std::is_same<Object, T>::value> * = nullptr>
+ bool match(T *obj) { return obj == obj_; }
+ bool match(Object *object) { return object == object_; }
+
+ Object *object() const { return object_; }
+
+ virtual void invokePack(BoundMethodPackBase *pack) = 0;
+
+protected:
+ bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
+ bool deleteMethod);
+
+ void *obj_;
+ Object *object_;
+
+private:
+ ConnectionType connectionType_;
+};
+
+template<typename R, typename... Args>
+class BoundMethodArgs : public BoundMethodBase
+{
+public:
+ using PackType = BoundMethodPack<R, Args...>;
+
+private:
+ template<std::size_t... I>
+ void invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)
+ {
+ PackType *args = static_cast<PackType *>(pack);
+ args->ret_ = invoke(std::get<I>(args->args_)...);
+ }
+
+public:
+ BoundMethodArgs(void *obj, Object *object, ConnectionType type)
+ : BoundMethodBase(obj, object, type) {}
+
+ void invokePack(BoundMethodPackBase *pack) override
+ {
+ invokePack(pack, std::make_index_sequence<sizeof...(Args)>{});
+ }
+
+ virtual R activate(Args... args, bool deleteMethod = false) = 0;
+ virtual R invoke(Args... args) = 0;
+};
+
+template<typename... Args>
+class BoundMethodArgs<void, Args...> : public BoundMethodBase
+{
+public:
+ using PackType = BoundMethodPack<void, Args...>;
+
+private:
+ template<std::size_t... I>
+ void invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)
+ {
+ /* args is effectively unused when the sequence I is empty. */
+ PackType *args [[gnu::unused]] = static_cast<PackType *>(pack);
+ invoke(std::get<I>(args->args_)...);
+ }
+
+public:
+ BoundMethodArgs(void *obj, Object *object, ConnectionType type)
+ : BoundMethodBase(obj, object, type) {}
+
+ void invokePack(BoundMethodPackBase *pack) override
+ {
+ invokePack(pack, std::make_index_sequence<sizeof...(Args)>{});
+ }
+
+ virtual void activate(Args... args, bool deleteMethod = false) = 0;
+ virtual void invoke(Args... args) = 0;
+};
+
+template<typename T, typename R, typename... Args>
+class BoundMethodMember : public BoundMethodArgs<R, Args...>
+{
+public:
+ using PackType = typename BoundMethodArgs<R, Args...>::PackType;
+
+ BoundMethodMember(T *obj, Object *object, R (T::*func)(Args...),
+ ConnectionType type = ConnectionTypeAuto)
+ : BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
+ {
+ }
+
+ bool match(R (T::*func)(Args...)) const { return func == func_; }
+
+ R activate(Args... args, bool deleteMethod = false) override
+ {
+ if (!this->object_) {
+ T *obj = static_cast<T *>(this->obj_);
+ return (obj->*func_)(args...);
+ }
+
+ auto pack = std::make_shared<PackType>(args...);
+ bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
+ return sync ? pack->ret_ : R();
+ }
+
+ R invoke(Args... args) override
+ {
+ T *obj = static_cast<T *>(this->obj_);
+ return (obj->*func_)(args...);
+ }
+
+private:
+ R (T::*func_)(Args...);
+};
+
+template<typename T, typename... Args>
+class BoundMethodMember<T, void, Args...> : public BoundMethodArgs<void, Args...>
+{
+public:
+ using PackType = typename BoundMethodArgs<void, Args...>::PackType;
+
+ BoundMethodMember(T *obj, Object *object, void (T::*func)(Args...),
+ ConnectionType type = ConnectionTypeAuto)
+ : BoundMethodArgs<void, Args...>(obj, object, type), func_(func)
+ {
+ }
+
+ bool match(void (T::*func)(Args...)) const { return func == func_; }
+
+ void activate(Args... args, bool deleteMethod = false) override
+ {
+ if (!this->object_) {
+ T *obj = static_cast<T *>(this->obj_);
+ return (obj->*func_)(args...);
+ }
+
+ auto pack = std::make_shared<PackType>(args...);
+ BoundMethodBase::activatePack(pack, deleteMethod);
+ }
+
+ void invoke(Args... args) override
+ {
+ T *obj = static_cast<T *>(this->obj_);
+ return (obj->*func_)(args...);
+ }
+
+private:
+ void (T::*func_)(Args...);
+};
+
+template<typename R, typename... Args>
+class BoundMethodStatic : public BoundMethodArgs<R, Args...>
+{
+public:
+ BoundMethodStatic(R (*func)(Args...))
+ : BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),
+ func_(func)
+ {
+ }
+
+ bool match(R (*func)(Args...)) const { return func == func_; }
+
+ R activate(Args... args, [[maybe_unused]] bool deleteMethod = false) override
+ {
+ return (*func_)(args...);
+ }
+
+ R invoke(Args...) override
+ {
+ return R();
+ }
+
+private:
+ R (*func_)(Args...);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_BASE_BOUND_METHOD_H__ */