diff options
-rw-r--r-- | include/libcamera/object.h | 12 | ||||
-rw-r--r-- | src/libcamera/bound_method.cpp | 2 | ||||
-rw-r--r-- | src/libcamera/include/message.h | 17 | ||||
-rw-r--r-- | src/libcamera/message.cpp | 48 | ||||
-rw-r--r-- | src/libcamera/object.cpp | 29 |
5 files changed, 86 insertions, 22 deletions
diff --git a/include/libcamera/object.h b/include/libcamera/object.h index e3b39cf5..869200a5 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -28,6 +28,16 @@ public: void postMessage(std::unique_ptr<Message> msg); + template<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr> + void invokeMethod(void (T::*func)(Args...), Args... args) + { + T *obj = static_cast<T *>(this); + BoundMethodBase *method = new BoundMemberMethod<T, Args...>(obj, this, func); + void *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... }; + + invokeMethod(method, pack); + } + Thread *thread() const { return thread_; } void moveToThread(Thread *thread); @@ -40,6 +50,8 @@ private: friend class BoundMethodBase; friend class Thread; + void invokeMethod(BoundMethodBase *method, void *pack); + void connect(SignalBase *signal); void disconnect(SignalBase *signal); diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp index 23b8f412..d89f84c0 100644 --- a/src/libcamera/bound_method.cpp +++ b/src/libcamera/bound_method.cpp @@ -19,7 +19,7 @@ void BoundMethodBase::activatePack(void *pack) invokePack(pack); } else { std::unique_ptr<Message> msg = - utils::make_unique<SignalMessage>(this, pack); + utils::make_unique<InvokeMessage>(this, pack); object_->postMessage(std::move(msg)); } } diff --git a/src/libcamera/include/message.h b/src/libcamera/include/message.h index b4670c0e..92717e31 100644 --- a/src/libcamera/include/message.h +++ b/src/libcamera/include/message.h @@ -9,6 +9,8 @@ #include <atomic> +#include <libcamera/bound_method.h> + namespace libcamera { class BoundMethodBase; @@ -20,7 +22,7 @@ class Message public: enum Type { None = 0, - SignalMessage = 1, + InvokeMessage = 1, UserMessage = 1000, }; @@ -41,16 +43,19 @@ private: static std::atomic_uint nextUserType_; }; -class SignalMessage : public Message +class InvokeMessage : public Message { public: - SignalMessage(BoundMethodBase *method, void *pack) - : Message(Message::SignalMessage), method_(method), pack_(pack) - { - } + InvokeMessage(BoundMethodBase *method, void *pack, + bool deleteMethod = false); + ~InvokeMessage(); + + void invoke(); +private: BoundMethodBase *method_; void *pack_; + bool deleteMethod_; }; } /* namespace libcamera */ diff --git a/src/libcamera/message.cpp b/src/libcamera/message.cpp index 8d3376d8..f6c39d40 100644 --- a/src/libcamera/message.cpp +++ b/src/libcamera/message.cpp @@ -7,6 +7,8 @@ #include "message.h" +#include <libcamera/signal.h> + #include "log.h" /** @@ -43,8 +45,8 @@ std::atomic_uint Message::nextUserType_{ Message::UserMessage }; * \brief The message type * \var Message::None * \brief Invalid message type - * \var Message::SignalMessage - * \brief Asynchronous signal delivery across threads + * \var Message::InvokeMessage + * \brief Asynchronous method invocation across threads * \var Message::UserMessage * \brief First value available for user-defined messages */ @@ -107,25 +109,47 @@ Message::Type Message::registerMessageType() } /** - * \class SignalMessage - * \brief A message carrying a Signal across threads + * \class InvokeMessage + * \brief A message carrying a method invocation across threads */ /** - * \fn SignalMessage::SignalMessage() - * \brief Construct a SignalMessage - * \param[in] method The slot that the signal targets - * \param[in] pack The signal arguments + * \brief Construct an InvokeMessage for method invocation on an Object + * \param[in] method The bound method + * \param[in] pack The packed method arguments + * \param[in] deleteMethod True to delete the \a method when the message is + * destroyed */ +InvokeMessage::InvokeMessage(BoundMethodBase *method, void *pack, + bool deleteMethod) + : Message(Message::InvokeMessage), method_(method), pack_(pack), + deleteMethod_(deleteMethod) +{ +} + +InvokeMessage::~InvokeMessage() +{ + if (deleteMethod_) + delete method_; +} + +/** + * \brief Invoke the method bound to InvokeMessage::method_ with arguments + * InvokeMessage::pack_ + */ +void InvokeMessage::invoke() +{ + method_->invokePack(pack_); +} /** - * \var SignalMessage::method_ - * \brief The slot that the signal targets + * \var InvokeMessage::method_ + * \brief The method to be invoked */ /** - * \var SignalMessage::pack_ - * \brief The signal arguments + * \var InvokeMessage::pack_ + * \brief The packed method invocation arguments */ }; /* namespace libcamera */ diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp index 0adbc203..7d70ce21 100644 --- a/src/libcamera/object.cpp +++ b/src/libcamera/object.cpp @@ -12,6 +12,7 @@ #include "log.h" #include "message.h" #include "thread.h" +#include "utils.h" /** * \file object.h @@ -88,9 +89,9 @@ void Object::postMessage(std::unique_ptr<Message> msg) void Object::message(Message *msg) { switch (msg->type()) { - case Message::SignalMessage: { - SignalMessage *smsg = static_cast<SignalMessage *>(msg); - smsg->method_->invokePack(smsg->pack_); + case Message::InvokeMessage: { + InvokeMessage *iMsg = static_cast<InvokeMessage *>(msg); + iMsg->invoke(); break; } @@ -100,6 +101,28 @@ void Object::message(Message *msg) } /** + * \fn void Object::invokeMethod(void (T::*func)(Args...), Args... args) + * \brief Invoke a method asynchronously on an Object instance + * \param[in] func The object method to invoke + * \param[in] args The method arguments + * + * This method invokes the member method \a func when control returns to the + * event loop of the object's thread. The method is executed in the object's + * thread with arguments \a args. + * + * Arguments \a args passed by value or reference are copied, while pointers + * are passed untouched. The caller shall ensure that any pointer argument + * remains valid until the method is invoked. + */ + +void Object::invokeMethod(BoundMethodBase *method, void *args) +{ + std::unique_ptr<Message> msg = + utils::make_unique<InvokeMessage>(method, args, true); + postMessage(std::move(msg)); +} + +/** * \fn Object::thread() * \brief Retrieve the thread the object is bound to * \return The thread the object is bound to |