1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: Message queues for inter-thread communication
4 // Author: Evgeniy Tarassov
7 // Copyright: (C) 2007 TT-Solutions SARL
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 #ifndef _WX_MSGQUEUE_H_
12 #define _WX_MSGQUEUE_H_
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 #include "wx/thread.h"
22 #include "wx/stopwatch.h"
24 #include "wx/beforestd.h"
26 #include "wx/afterstd.h"
28 enum wxMessageQueueError
30 wxMSGQUEUE_NO_ERROR
= 0, // operation completed successfully
31 wxMSGQUEUE_TIMEOUT
, // no messages received before timeout expired
32 wxMSGQUEUE_MISC_ERROR
// some unexpected (and fatal) error has occurred
35 // ---------------------------------------------------------------------------
36 // Message queue allows passing message between threads.
38 // This class is typically used for communicating between the main and worker
39 // threads. The main thread calls Post() and the worker thread calls Receive().
41 // For this class a message is an object of arbitrary type T. Notice that
42 // typically there must be some special message indicating that the thread
43 // should terminate as there is no other way to gracefully shutdown a thread
44 // waiting on the message queue.
45 // ---------------------------------------------------------------------------
50 // The type of the messages transported by this queue
53 // Default ctor creates an initially empty queue
55 : m_conditionNotEmpty(m_mutex
)
59 // Add a message to this queue and signal the threads waiting for messages.
61 // This method is safe to call from multiple threads in parallel.
62 wxMessageQueueError
Post(const Message
& msg
)
64 wxMutexLocker
locker(m_mutex
);
66 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
70 m_conditionNotEmpty
.Signal();
72 return wxMSGQUEUE_NO_ERROR
;
75 // Remove all messages from the queue.
77 // This method is meant to be called from the same thread(s) that call
78 // Post() to discard any still pending requests if they became unnecessary.
79 wxMessageQueueError
Clear()
81 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
83 wxMutexLocker
locker(m_mutex
);
86 std::swap(m_messages
, empty
);
88 return wxMSGQUEUE_NO_ERROR
;
91 // Wait no more than timeout milliseconds until a message becomes available.
93 // Setting timeout to 0 is equivalent to an infinite timeout. See Receive().
94 wxMessageQueueError
ReceiveTimeout(long timeout
, T
& msg
)
96 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
98 wxMutexLocker
locker(m_mutex
);
100 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
102 const wxMilliClock_t waitUntil
= wxGetLocalTimeMillis() + timeout
;
103 while ( m_messages
.empty() )
105 wxCondError result
= m_conditionNotEmpty
.WaitTimeout(timeout
);
107 if ( result
== wxCOND_NO_ERROR
)
110 wxCHECK( result
== wxCOND_TIMEOUT
, wxMSGQUEUE_MISC_ERROR
);
112 const wxMilliClock_t now
= wxGetLocalTimeMillis();
114 if ( now
>= waitUntil
)
115 return wxMSGQUEUE_TIMEOUT
;
117 timeout
= (waitUntil
- now
).ToLong();
118 wxASSERT(timeout
> 0);
121 msg
= m_messages
.front();
124 return wxMSGQUEUE_NO_ERROR
;
127 // Same as ReceiveTimeout() but waits for as long as it takes for a message
128 // to become available (so it can't return wxMSGQUEUE_TIMEOUT)
129 wxMessageQueueError
Receive(T
& msg
)
131 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR
);
133 wxMutexLocker
locker(m_mutex
);
135 wxCHECK( locker
.IsOk(), wxMSGQUEUE_MISC_ERROR
);
137 while ( m_messages
.empty() )
139 wxCondError result
= m_conditionNotEmpty
.Wait();
141 wxCHECK( result
== wxCOND_NO_ERROR
, wxMSGQUEUE_MISC_ERROR
);
144 msg
= m_messages
.front();
147 return wxMSGQUEUE_NO_ERROR
;
150 // Return false only if there was a fatal error in ctor
153 return m_conditionNotEmpty
.IsOk();
157 // Disable copy ctor and assignment operator
158 wxMessageQueue(const wxMessageQueue
<T
>& rhs
);
159 wxMessageQueue
<T
>& operator=(const wxMessageQueue
<T
>& rhs
);
161 mutable wxMutex m_mutex
;
162 wxCondition m_conditionNotEmpty
;
164 std::queue
<T
> m_messages
;
167 #endif // wxUSE_THREADS
169 #endif // _WX_MSGQUEUE_H_