summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/bound_method.cpp22
-rw-r--r--test/object-invoke.cpp20
2 files changed, 34 insertions, 8 deletions
diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp
index e18c2eb4..9aa59dc3 100644
--- a/src/libcamera/bound_method.cpp
+++ b/src/libcamera/bound_method.cpp
@@ -35,16 +35,19 @@ namespace libcamera {
* thread.
*
* \var ConnectionType::ConnectionTypeQueued
- * \brief The receiver is invoked asynchronously in its thread when control
- * returns to the thread's event loop. The sender proceeds without waiting for
- * the invocation to complete.
+ * \brief The receiver is invoked asynchronously
+ *
+ * Invoke the receiver asynchronously in its thread when control returns to the
+ * thread's event loop. The sender proceeds without waiting for the invocation
+ * to complete.
*
* \var ConnectionType::ConnectionTypeBlocking
- * \brief The receiver is invoked asynchronously in its thread when control
- * returns to the thread's event loop. The sender blocks until the receiver
- * signals the completion of the invocation. This connection type shall not be
- * used when the sender and receiver live in the same thread, otherwise
- * deadlock will occur.
+ * \brief The receiver is invoked synchronously
+ *
+ * If the sender and the receiver live in the same thread, this is equivalent to
+ * ConnectionTypeDirect. Otherwise, the receiver is invoked asynchronously in
+ * its thread when control returns to the thread's event loop. The sender
+ * blocks until the receiver signals the completion of the invocation.
*/
/**
@@ -71,6 +74,9 @@ bool BoundMethodBase::activatePack(std::shared_ptr<BoundMethodPackBase> pack,
type = ConnectionTypeDirect;
else
type = ConnectionTypeQueued;
+ } else if (type == ConnectionTypeBlocking) {
+ if (Thread::current() == object_->thread())
+ type = ConnectionTypeDirect;
}
switch (type) {
diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp
index 8e2055ca..fa162c83 100644
--- a/test/object-invoke.cpp
+++ b/test/object-invoke.cpp
@@ -101,6 +101,26 @@ protected:
}
/*
+ * Test that blocking invocation is delivered directly when the
+ * caller and callee live in the same thread.
+ */
+ object_.reset();
+
+ object_.invokeMethod(&InvokedObject::method,
+ ConnectionTypeBlocking, 42);
+
+ switch (object_.status()) {
+ case InvokedObject::NoCall:
+ cout << "Method not invoked for main thread (blocking)" << endl;
+ return TestFail;
+ case InvokedObject::InvalidThread:
+ cout << "Method invoked in incorrect thread for main thread (blocking)" << endl;
+ return TestFail;
+ default:
+ break;
+ }
+
+ /*
* Move the object to a thread and verify that auto method
* invocation is delivered in the correct thread.
*/