00001
00002
00003
00004
00005
00006
00007
00008
00010
00011 #ifndef _WX_MSGQUEUE_VRUT_H_
00012 #define _WX_MSGQUEUE_VRUT_H_
00013
00014
00015
00016
00017
00018 #include <wx/thread.h>
00019
00020 #if wxUSE_THREADS
00021
00022 #include <wx/stopwatch.h>
00023
00024 #include <wx/beforestd.h>
00025 #include <deque>
00026 #include <wx/afterstd.h>
00027
00028 namespace VRUT
00029 {
00030 enum MessageQueueError
00031 {
00032 wxMSGQUEUE_NO_ERROR = 0,
00033 wxMSGQUEUE_TIMEOUT,
00034 wxMSGQUEUE_MISC_ERROR
00035 };
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 template <typename T>
00049 class MessageQueue
00050 {
00051 public:
00052
00053 typedef T Message;
00054
00055
00056 MessageQueue()
00057 : m_conditionNotEmpty(m_mutex), hPrioMesCount(0)
00058 {
00059 }
00060
00065 MessageQueueError Post(const Message& msg, bool highPrio = false)
00066 {
00067 wxMutexLocker locker(m_mutex);
00068
00069 wxCHECK( locker.IsOk(), wxMSGQUEUE_MISC_ERROR );
00070
00072 if (m_messages.size() > 0xffffff)
00073 return wxMSGQUEUE_MISC_ERROR;
00074
00075 if (highPrio)
00076 {
00077 typename std::list<T>::iterator normMes = m_messages.begin();
00078 for (size_t i=0; i<hPrioMesCount; i++)
00079 normMes++;
00080 m_messages.insert(normMes, msg);
00081 hPrioMesCount++;
00082 }
00083 else
00084 m_messages.push_back(msg);
00085
00086 m_conditionNotEmpty.Signal();
00087
00088 return wxMSGQUEUE_NO_ERROR;
00089 }
00090
00091
00092
00093
00094 T ReceiveTimeout(long timeout, MessageQueueError & err)
00095 {
00096 err = wxMSGQUEUE_MISC_ERROR;
00097 if (!IsOk())
00098 return T();
00099
00100 wxMutexLocker locker(m_mutex);
00101
00102 if (!locker.IsOk())
00103 return T();
00104
00105 const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout;
00106 while ( m_messages.empty() )
00107 {
00108 wxCondError result = m_conditionNotEmpty.WaitTimeout(timeout);
00109
00110 if ( result == wxCOND_NO_ERROR )
00111 continue;
00112
00113 if (result != wxCOND_TIMEOUT)
00114 return T();
00115
00116 const wxMilliClock_t now = wxGetLocalTimeMillis();
00117
00118 if ( now >= waitUntil )
00119 {
00120 err = wxMSGQUEUE_TIMEOUT;
00121 return T();
00122 }
00123
00124 timeout = (waitUntil - now).ToLong();
00125 wxASSERT(timeout > 0);
00126 }
00127
00128 T ret = m_messages.front();
00129 m_messages.pop_front();
00130 if (hPrioMesCount>0)
00131 hPrioMesCount--;
00132
00133 err = wxMSGQUEUE_NO_ERROR;
00134 return ret;
00135 }
00136
00138 T CheckFirst() const
00139 {
00140 if (!IsOk())
00141 return T();
00142
00143 wxMutexLocker locker(m_mutex);
00144
00145 if (!locker.IsOk() || m_messages.empty())
00146 return T();
00147
00148 return m_messages.front();
00149 }
00150
00151
00153 T GetLast(bool remove = false)
00154 {
00155 if (!IsOk())
00156 return T();
00157
00158 wxMutexLocker locker(m_mutex);
00159
00160 if (!locker.IsOk() || m_messages.empty())
00161 return T();
00162
00163 if (remove)
00164 {
00165
00166 T ret = m_messages.back();
00167 m_messages.pop_back();
00168 return ret;
00169 }
00170 else
00171 return m_messages.back();
00172 }
00173
00174
00175 bool IsOk() const
00176 {
00177 return m_conditionNotEmpty.IsOk();
00178 }
00179
00181 size_t GetSize() const
00182 {
00183 wxMutexLocker locker(m_mutex);
00184 return m_messages.size();
00185 }
00186
00188 void Clear()
00189 {
00190 wxMutexLocker locker(m_mutex);
00191 m_messages.clear();
00192 }
00193
00194 private:
00195
00196 MessageQueue(const MessageQueue<T>& rhs);
00197 MessageQueue<T>& operator=(const MessageQueue<T>& rhs);
00198
00199 mutable wxMutex m_mutex;
00200 wxCondition m_conditionNotEmpty;
00201
00202 std::list<T> m_messages;
00203 size_t hPrioMesCount;
00204 };
00205 };
00206 #endif // wxUSE_THREADS
00207
00208 #endif // _WX_MSGQUEUE_VRUT_H_