summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/object.h12
-rw-r--r--src/libcamera/bound_method.cpp2
-rw-r--r--src/libcamera/include/message.h17
-rw-r--r--src/libcamera/message.cpp48
-rw-r--r--src/libcamera/object.cpp29
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