libcamera: signal: Split Slot implementation to reusable classes
Move the Slot* classes to bound_method.{h,cpp} and rename them to Bound*Method*. They will be reused to implement asynchronous method invocation similar to cross-thread signal delivery. This is only a move and rename, no functional changes are included. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
parent
a66e5ca8c6
commit
0e65ed8145
11 changed files with 197 additions and 166 deletions
131
include/libcamera/bound_method.h
Normal file
131
include/libcamera/bound_method.h
Normal file
|
@ -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__ */
|
Loading…
Add table
Add a link
Reference in a new issue