]> git.saurik.com Git - wxWidgets.git/blame - include/wx/msgqueue.h
Don't define __STRICT_ANSI__, we should build both with and without it.
[wxWidgets.git] / include / wx / msgqueue.h
CommitLineData
6aaee6af 1///////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: wx/msqqueue.h
6aaee6af
VZ
3// Purpose: Message queues for inter-thread communication
4// Author: Evgeniy Tarassov
5// Created: 2007-10-31
6aaee6af
VZ
6// Copyright: (C) 2007 TT-Solutions SARL
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10#ifndef _WX_MSGQUEUE_H_
11#define _WX_MSGQUEUE_H_
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17#include "wx/thread.h"
18
19#if wxUSE_THREADS
20
855b9ce0
VZ
21#include "wx/stopwatch.h"
22
6aaee6af
VZ
23#include "wx/beforestd.h"
24#include <queue>
25#include "wx/afterstd.h"
26
27enum wxMessageQueueError
28{
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
32};
33
34// ---------------------------------------------------------------------------
35// Message queue allows passing message between threads.
36//
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().
39//
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// ---------------------------------------------------------------------------
45template <typename T>
46class wxMessageQueue
47{
48public:
49 // The type of the messages transported by this queue
50 typedef T Message;
51
52 // Default ctor creates an initially empty queue
53 wxMessageQueue()
54 : m_conditionNotEmpty(m_mutex)
55 {
56 }
57
58 // Add a message to this queue and signal the threads waiting for messages.
59 //
60 // This method is safe to call from multiple threads in parallel.
61 wxMessageQueueError Post(const Message& msg)
62 {
63 wxMutexLocker locker(m_mutex);
64
65 wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
66
67 m_messages.push(msg);
68
69 m_conditionNotEmpty.Signal();
70
71 return wxMSGQUEUE_NO_ERROR;
72 }
73
d25a864d
VZ
74 // Remove all messages from the queue.
75 //
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()
79 {
80 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR );
81
82 wxMutexLocker locker(m_mutex);
83
84 std::queue<T> empty;
85 std::swap(m_messages, empty);
86
87 return wxMSGQUEUE_NO_ERROR;
88 }
89
6aaee6af
VZ
90 // Wait no more than timeout milliseconds until a message becomes available.
91 //
92 // Setting timeout to 0 is equivalent to an infinite timeout. See Receive().
93 wxMessageQueueError ReceiveTimeout(long timeout, T& msg)
94 {
95 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR );
96
97 wxMutexLocker locker(m_mutex);
98
99 wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
100
101 const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout;
102 while ( m_messages.empty() )
103 {
104 wxCondError result = m_conditionNotEmpty.WaitTimeout(timeout);
105
106 if ( result == wxCOND_NO_ERROR )
107 continue;
108
109 wxCHECK( result == wxCOND_TIMEOUT, wxMSGQUEUE_MISC_ERROR );
110
111 const wxMilliClock_t now = wxGetLocalTimeMillis();
112
113 if ( now >= waitUntil )
114 return wxMSGQUEUE_TIMEOUT;
115
116 timeout = (waitUntil - now).ToLong();
117 wxASSERT(timeout > 0);
118 }
119
120 msg = m_messages.front();
121 m_messages.pop();
122
123 return wxMSGQUEUE_NO_ERROR;
124 }
125
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)
129 {
130 wxCHECK( IsOk(), wxMSGQUEUE_MISC_ERROR );
131
132 wxMutexLocker locker(m_mutex);
133
134 wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
135
136 while ( m_messages.empty() )
137 {
138 wxCondError result = m_conditionNotEmpty.Wait();
139
140 wxCHECK( result == wxCOND_NO_ERROR, wxMSGQUEUE_MISC_ERROR );
141 }
142
143 msg = m_messages.front();
144 m_messages.pop();
145
146 return wxMSGQUEUE_NO_ERROR;
147 }
148
149 // Return false only if there was a fatal error in ctor
150 bool IsOk() const
151 {
152 return m_conditionNotEmpty.IsOk();
153 }
154
155private:
156 // Disable copy ctor and assignment operator
157 wxMessageQueue(const wxMessageQueue<T>& rhs);
158 wxMessageQueue<T>& operator=(const wxMessageQueue<T>& rhs);
159
160 mutable wxMutex m_mutex;
161 wxCondition m_conditionNotEmpty;
162
163 std::queue<T> m_messages;
164};
165
166#endif // wxUSE_THREADS
167
168#endif // _WX_MSGQUEUE_H_