--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/thread.h
+// Purpose: Message queues for inter-thread communication
+// Author: Evgeniy Tarassov
+// Created: 2007-10-31
+// RCS-ID: $Id$
+// Copyright: (C) 2007 TT-Solutions SARL
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_MSGQUEUE_H_
+#define _WX_MSGQUEUE_H_
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/thread.h"
+
+#if wxUSE_THREADS
+
+#include "wx/beforestd.h"
+#include <queue>
+#include "wx/afterstd.h"
+
+enum wxMessageQueueError
+{
+ wxMSGQUEUE_NO_ERROR = 0, // operation completed successfully
+ wxMSGQUEUE_TIMEOUT, // no messages received before timeout expired
+ wxMSGQUEUE_MISC_ERROR // some unexpected (and fatal) error has occurred
+};
+
+// ---------------------------------------------------------------------------
+// Message queue allows passing message between threads.
+//
+// This class is typically used for communicating between the main and worker
+// threads. The main thread calls Post() and the worker thread calls Receive().
+//
+// For this class a message is an object of arbitrary type T. Notice that
+// typically there must be some special message indicating that the thread
+// should terminate as there is no other way to gracefully shutdown a thread
+// waiting on the message queue.
+// ---------------------------------------------------------------------------
+template <typename T>
+class wxMessageQueue
+{
+public:
+ // The type of the messages transported by this queue
+ typedef T Message;
+
+ // Default ctor creates an initially empty queue
+ wxMessageQueue()
+ : m_conditionNotEmpty(m_mutex)
+ {
+ }
+
+ // Add a message to this queue and signal the threads waiting for messages.
+ //
+ // This method is safe to call from multiple threads in parallel.
+ wxMessageQueueError Post(const Message& msg)
+ {
+ wxMutexLocker locker(m_mutex);
+
+ wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
+
+ m_messages.push(msg);
+
+ m_conditionNotEmpty.Signal();
+
+ return wxMSGQUEUE_NO_ERROR;
+ }
+
+ // Wait no more than timeout milliseconds until a message becomes available.
+ //
+ // Setting timeout to 0 is equivalent to an infinite timeout. See Receive().
+ wxMessageQueueError ReceiveTimeout(long timeout, T& msg)
+ {
+ wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR );
+
+ wxMutexLocker locker(m_mutex);
+
+ wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
+
+ const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout;
+ while ( m_messages.empty() )
+ {
+ wxCondError result = m_conditionNotEmpty.WaitTimeout(timeout);
+
+ if ( result == wxCOND_NO_ERROR )
+ continue;
+
+ wxCHECK( result == wxCOND_TIMEOUT, wxMSGQUEUE_MISC_ERROR );
+
+ const wxMilliClock_t now = wxGetLocalTimeMillis();
+
+ if ( now >= waitUntil )
+ return wxMSGQUEUE_TIMEOUT;
+
+ timeout = (waitUntil - now).ToLong();
+ wxASSERT(timeout > 0);
+ }
+
+ msg = m_messages.front();
+ m_messages.pop();
+
+ return wxMSGQUEUE_NO_ERROR;
+ }
+
+ // Same as ReceiveTimeout() but waits for as long as it takes for a message
+ // to become available (so it can't return wxMSGQUEUE_TIMEOUT)
+ wxMessageQueueError Receive(T& msg)
+ {
+ wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR );
+
+ wxMutexLocker locker(m_mutex);
+
+ wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
+
+ while ( m_messages.empty() )
+ {
+ wxCondError result = m_conditionNotEmpty.Wait();
+
+ wxCHECK( result == wxCOND_NO_ERROR, wxMSGQUEUE_MISC_ERROR );
+ }
+
+ msg = m_messages.front();
+ m_messages.pop();
+
+ return wxMSGQUEUE_NO_ERROR;
+ }
+
+ // Return false only if there was a fatal error in ctor
+ bool IsOk() const
+ {
+ return m_conditionNotEmpty.IsOk();
+ }
+
+private:
+ // Disable copy ctor and assignment operator
+ wxMessageQueue(const wxMessageQueue<T>& rhs);
+ wxMessageQueue<T>& operator=(const wxMessageQueue<T>& rhs);
+
+ mutable wxMutex m_mutex;
+ wxCondition m_conditionNotEmpty;
+
+ std::queue<T> m_messages;
+};
+
+#endif // wxUSE_THREADS
+
+#endif // _WX_MSGQUEUE_H_