Allow using move-only types with wxMessageQueue

Add Post() overload taking r-value reference and a unit test showing
that we can use it with a non-copyable type.
This commit is contained in:
Vadim Zeitlin
2024-12-26 15:19:08 +01:00
parent 65c8b058ef
commit f5eb38410d
3 changed files with 53 additions and 2 deletions
+19 -2
View File
@@ -22,6 +22,7 @@
#include "wx/beforestd.h"
#include <queue>
#include <utility>
#include "wx/afterstd.h"
enum wxMessageQueueError
@@ -58,6 +59,8 @@ public:
// Add a message to this queue and signal the threads waiting for messages.
//
// This method is safe to call from multiple threads in parallel.
//
// This overload relies on Message being copyable.
wxMessageQueueError Post(const Message& msg)
{
wxMutexLocker locker(m_mutex);
@@ -71,6 +74,20 @@ public:
return wxMSGQUEUE_NO_ERROR;
}
// Overload for move-only types.
wxMessageQueueError Post(Message&& msg)
{
wxMutexLocker locker(m_mutex);
wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
m_messages.push(std::move(msg));
m_conditionNotEmpty.Signal();
return wxMSGQUEUE_NO_ERROR;
}
// Remove all messages from the queue.
//
// This method is meant to be called from the same thread(s) that call
@@ -117,7 +134,7 @@ public:
wxASSERT(timeout > 0);
}
msg = m_messages.front();
msg = std::move(m_messages.front());
m_messages.pop();
return wxMSGQUEUE_NO_ERROR;
@@ -140,7 +157,7 @@ public:
wxCHECK( result == wxCOND_NO_ERROR, wxMSGQUEUE_MISC_ERROR );
}
msg = m_messages.front();
msg = std::move(m_messages.front());
m_messages.pop();
return wxMSGQUEUE_NO_ERROR;
+10
View File
@@ -86,6 +86,16 @@ public:
*/
wxMessageQueueError Post(T const& msg);
/**
Post a message of move-only type.
This function has the same semantics as the other overload but can be
used for non-copyable (but movable) types.
@since 3.3.0
*/
wxMessageQueueError Post(T&& msg);
/**
Block until a message becomes available in the queue.
Waits indefinitely long or until an error occurs.
+24
View File
@@ -191,3 +191,27 @@ void *MyThread::Entry()
return (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR;
}
TEST_CASE("wxMessageQueue::NonCopyable", "[msgqueue]")
{
struct NonCopyable
{
explicit NonCopyable(int n) : m_n(new int(n)) { }
NonCopyable(NonCopyable&& other) = default;
NonCopyable& operator=(NonCopyable&& other) = default;
std::unique_ptr<int> m_n;
};
wxMessageQueue<NonCopyable> queue;
NonCopyable nc(17);
CHECK( queue.Post(std::move(nc)) == wxMSGQUEUE_NO_ERROR );
NonCopyable nc2(0);
CHECK( queue.Receive(nc2) == wxMSGQUEUE_NO_ERROR );
CHECK( *nc2.m_n == 17 );
CHECK( queue.ReceiveTimeout(0, nc2) == wxMSGQUEUE_TIMEOUT );
}