1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: Message queues for inter-thread communication
4 // Author: Evgeniy Tarassov
6 // Copyright: (C) 2007 TT-Solutions SARL
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 #ifndef _WX_MSGQUEUE_H_
11 #define _WX_MSGQUEUE_H_
13 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
17 #include "wx/thread.h"
21 #include "wx/stopwatch.h"
23 #include "wx/beforestd.h"
25 #include "wx/afterstd.h"
27 enum wxMessageQueueError
29 wxMSGQUEUE_NO_ERROR
= 0, // operation completed successfully
30 wxMSGQUEUE_TIMEOUT
, // no messages received before timeout expired
31 wxMSGQUEUE_MISC_ERROR
// some unexpected (and fatal) error has occurred
34 // ---------------------------------------------------------------------------
35 // Message queue allows passing message between threads.
37 // This class is typically used for communicating between the main and worker
38 // threads. The main thread calls Post() and the worker thread calls Receive().
40 // For this class a message is an object of arbitrary type T. Notice that
41 // typically there must be some special message indicating that the thread
42 // should terminate as there is no other way to gracefully shutdown a thread
43 // waiting on the message queue.
44 // ---------------------------------------------------------------------------
49 // The type of the messages transported by this queue
52 // Default ctor creates an initially empty queue
54 : m_conditionNotEmpty(m_mutex
)
58 // Add a message to this queue and signal the threads waiting for messages.
60 // This method is safe to call from multiple threads in parallel.
61 wxMessageQueueError
Post(const Message
& msg
)
63 wxMutexLocker
locker(m_mutex
);
65 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
69 m_conditionNotEmpty
.Signal();
71 return wxMSGQUEUE_NO_ERROR
;
74 // Remove all messages from the queue.
76 // This method is meant to be called from the same thread(s) that call
77 // Post() to discard any still pending requests if they became unnecessary.
78 wxMessageQueueError
Clear()
80 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
82 wxMutexLocker
locker(m_mutex
);
85 std::swap(m_messages
, empty
);
87 return wxMSGQUEUE_NO_ERROR
;
90 // Wait no more than timeout milliseconds until a message becomes available.
92 // Setting timeout to 0 is equivalent to an infinite timeout. See Receive().
93 wxMessageQueueError
ReceiveTimeout(long timeout
, T
& msg
)
95 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
97 wxMutexLocker
locker(m_mutex
);
99 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
101 const wxMilliClock_t waitUntil
= wxGetLocalTimeMillis() + timeout
;
102 while ( m_messages
.empty() )
104 wxCondError result
= m_conditionNotEmpty
.WaitTimeout(timeout
);
106 if ( result
== wxCOND_NO_ERROR
)
109 wxCHECK( result
== wxCOND_TIMEOUT
, wxMSGQUEUE_MISC_ERROR
);
111 const wxMilliClock_t now
= wxGetLocalTimeMillis();
113 if ( now
>= waitUntil
)
114 return wxMSGQUEUE_TIMEOUT
;
116 timeout
= (waitUntil
- now
).ToLong();
117 wxASSERT(timeout
> 0);
120 msg
= m_messages
.front();
123 return wxMSGQUEUE_NO_ERROR
;
126 // Same as ReceiveTimeout() but waits for as long as it takes for a message
127 // to become available (so it can't return wxMSGQUEUE_TIMEOUT)
128 wxMessageQueueError
Receive(T
& msg
)
130 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
132 wxMutexLocker
locker(m_mutex
);
134 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
136 while ( m_messages
.empty() )
138 wxCondError result
= m_conditionNotEmpty
.Wait();
140 wxCHECK( result
== wxCOND_NO_ERROR
, wxMSGQUEUE_MISC_ERROR
);
143 msg
= m_messages
.front();
146 return wxMSGQUEUE_NO_ERROR
;
149 // Return false only if there was a fatal error in ctor
152 return m_conditionNotEmpty
.IsOk();
156 // Disable copy ctor and assignment operator
157 wxMessageQueue(const wxMessageQueue
<T
>& rhs
);
158 wxMessageQueue
<T
>& operator=(const wxMessageQueue
<T
>& rhs
);
160 mutable wxMutex m_mutex
;
161 wxCondition m_conditionNotEmpty
;
163 std::queue
<T
> m_messages
;
166 #endif // wxUSE_THREADS
168 #endif // _WX_MSGQUEUE_H_