summaryrefslogtreecommitdiff
path: root/include/libcamera/bound_method.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libcamera/bound_method.h')
-rw-r--r--include/libcamera/bound_method.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h
new file mode 100644
index 00000000..38c44b92
--- /dev/null
+++ b/include/libcamera/bound_method.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * bound_method.h - Method bind and invocation
+ */
+#ifndef __LIBCAMERA_BOUND_METHOD_H__
+#define __LIBCAMERA_BOUND_METHOD_H__
+
+#include <tuple>
+#include <type_traits>
+
+namespace libcamera {
+
+class Object;
+template<typename... Args>
+class Signal;
+class SignalBase;
+
+class BoundMethodBase
+{
+public:
+ BoundMethodBase(void *obj, Object *object)
+ : obj_(obj), object_(object) {}
+ virtual ~BoundMethodBase() {}
+
+ template<typename T, typename std::enable_if<!std::is_same<Object, T>::value>::type * = nullptr>
+ bool match(T *obj) { return obj == obj_; }
+ bool match(Object *object) { return object == object_; }
+
+ void disconnect(SignalBase *signal);
+
+ void activatePack(void *pack);
+ virtual void invokePack(void *pack) = 0;
+
+protected:
+ void *obj_;
+ Object *object_;
+};
+
+template<typename... Args>
+class BoundMethodArgs : public BoundMethodBase
+{
+private:
+#ifndef __DOXYGEN__
+ /*
+ * This is a cheap partial implementation of std::integer_sequence<>
+ * from C++14.
+ */
+ template<int...>
+ struct sequence {
+ };
+
+ template<int N, int... S>
+ struct generator : generator<N-1, N-1, S...> {
+ };
+
+ template<int... S>
+ struct generator<0, S...> {
+ typedef sequence<S...> type;
+ };
+#endif
+
+ using PackType = std::tuple<typename std::remove_reference<Args>::type...>;
+
+ template<int... S>
+ void invokePack(void *pack, sequence<S...>)
+ {
+ PackType *args = static_cast<PackType *>(pack);
+ invoke(std::get<S>(*args)...);
+ delete args;
+ }
+
+public:
+ BoundMethodArgs(void *obj, Object *object)
+ : BoundMethodBase(obj, object) {}
+
+ void invokePack(void *pack) override
+ {
+ invokePack(pack, typename generator<sizeof...(Args)>::type());
+ }
+
+ virtual void activate(Args... args) = 0;
+ virtual void invoke(Args... args) = 0;
+};
+
+template<typename T, typename... Args>
+class BoundMemberMethod : public BoundMethodArgs<Args...>
+{
+public:
+ using PackType = std::tuple<typename std::remove_reference<Args>::type...>;
+
+ BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...))
+ : BoundMethodArgs<Args...>(obj, object), func_(func) {}
+
+ void activate(Args... args)
+ {
+ if (this->object_)
+ BoundMethodBase::activatePack(new PackType{ args... });
+ else
+ (static_cast<T *>(this->obj_)->*func_)(args...);
+ }
+
+ void invoke(Args... args)
+ {
+ (static_cast<T *>(this->obj_)->*func_)(args...);
+ }
+
+private:
+ friend class Signal<Args...>;
+ void (T::*func_)(Args...);
+};
+
+template<typename... Args>
+class BoundStaticMethod : public BoundMethodArgs<Args...>
+{
+public:
+ BoundStaticMethod(void (*func)(Args...))
+ : BoundMethodArgs<Args...>(nullptr, nullptr), func_(func) {}
+
+ void activate(Args... args) { (*func_)(args...); }
+ void invoke(Args... args) {}
+
+private:
+ friend class Signal<Args...>;
+ void (*func_)(Args...);
+};
+
+}; /* namespace libcamera */
+
+#endif /* __LIBCAMERA_BOUND_METHOD_H__ */