fixed deadlock when calling wxPostEvent() from worker thread
[wxWidgets.git] / src / dfb / evtloop.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/evtloop.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Vaclav Slavik
5 // Created: 2006-08-16
6 // RCS-ID: $Id$
7 // Copyright: (c) 2006 REA Elektronik GmbH
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ===========================================================================
12 // declarations
13 // ===========================================================================
14
15 // ---------------------------------------------------------------------------
16 // headers
17 // ---------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #include "wx/evtloop.h"
23
24 #ifndef WX_PRECOMP
25 #include "wx/app.h"
26 #endif
27
28 #include "wx/thread.h"
29 #include "wx/timer.h"
30 #include "wx/private/socketevtdispatch.h"
31 #include "wx/dfb/private.h"
32
33 #define TRACE_EVENTS _T("events")
34
35 // ===========================================================================
36 // implementation
37 // ===========================================================================
38
39 //-----------------------------------------------------------------------------
40 // wxEventLoop initialization
41 //-----------------------------------------------------------------------------
42
43 wxIDirectFBEventBufferPtr wxEventLoop::ms_buffer;
44
45 wxEventLoop::wxEventLoop()
46 {
47 if ( !ms_buffer )
48 InitBuffer();
49 }
50
51 /* static */
52 void wxEventLoop::InitBuffer()
53 {
54 ms_buffer = wxIDirectFB::Get()->CreateEventBuffer();
55 }
56
57 /* static */
58 void wxEventLoop::CleanUp()
59 {
60 ms_buffer.Reset();
61 }
62
63 /* static */
64 wxIDirectFBEventBufferPtr wxEventLoop::GetDirectFBEventBuffer()
65 {
66 if ( !ms_buffer )
67 InitBuffer();
68
69 return ms_buffer;
70 }
71
72 //-----------------------------------------------------------------------------
73 // events dispatch and loop handling
74 //-----------------------------------------------------------------------------
75
76 bool wxEventLoop::Pending() const
77 {
78 wxCHECK_MSG( ms_buffer, false, _T("invalid event buffer") );
79
80 return ms_buffer->HasEvent();
81 }
82
83 bool wxEventLoop::Dispatch()
84 {
85 wxCHECK_MSG( ms_buffer, false, _T("invalid event buffer") );
86
87 // NB: we don't block indefinitely waiting for an event, but instead
88 // time out after a brief period in order to make sure that
89 // OnNextIteration() will be called frequently enough
90 const int TIMEOUT = 100;
91
92 // release the GUI mutex so that other threads have a chance to post
93 // events:
94 wxMutexGuiLeave();
95
96 bool rv = ms_buffer->WaitForEventWithTimeout(0, TIMEOUT);
97
98 // and acquire it back before calling any event handlers:
99 wxMutexGuiEnter();
100
101 if ( rv )
102 {
103 switch ( ms_buffer->GetLastResult() )
104 {
105 case DFB_OK:
106 {
107 wxDFBEvent e;
108 ms_buffer->GetEvent(e);
109 HandleDFBEvent(e);
110 break;
111 }
112
113 case DFB_TIMEOUT:
114 // timed out, pretend we processed an event so that
115 // OnNextIteration is called
116 break;
117
118 default:
119 // don't terminate the loop due to errors (they were reported
120 // already by ms_buffer)
121 break;
122 }
123 }
124
125 return true;
126 }
127
128 void wxEventLoop::WakeUp()
129 {
130 wxCHECK_RET( ms_buffer, _T("invalid event buffer") );
131
132 ms_buffer->WakeUp();
133 }
134
135 void wxEventLoop::OnNextIteration()
136 {
137 #if wxUSE_TIMER
138 wxTimer::NotifyTimers();
139 #endif
140
141 #if wxUSE_SOCKETS
142 // handle any pending socket events:
143 wxSocketEventDispatcher::Get().RunLoop();
144 #endif
145 }
146
147 void wxEventLoop::Yield()
148 {
149 // process all pending events:
150 while ( Pending() )
151 Dispatch();
152
153 // handle timers, sockets etc.
154 OnNextIteration();
155 }
156
157
158 //-----------------------------------------------------------------------------
159 // DirectFB -> wxWidgets events translation
160 //-----------------------------------------------------------------------------
161
162 void wxEventLoop::HandleDFBEvent(const wxDFBEvent& event)
163 {
164 switch ( event.GetClass() )
165 {
166 case DFEC_WINDOW:
167 {
168 wxDFBWindowEvent winevent(((const DFBEvent&)event).window);
169 wxTopLevelWindowDFB::HandleDFBWindowEvent(winevent);
170 break;
171 }
172
173 case DFEC_NONE:
174 case DFEC_INPUT:
175 case DFEC_USER:
176 #if wxCHECK_DFB_VERSION(0,9,23)
177 case DFEC_UNIVERSAL:
178 #endif
179 {
180 wxLogTrace(TRACE_EVENTS,
181 _T("ignoring event of unsupported class %i"),
182 (int)event.GetClass());
183 }
184 }
185 }