]> git.saurik.com Git - wxWidgets.git/blob - src/unix/wakeuppipe.cpp
avoid duplicate move events
[wxWidgets.git] / src / unix / wakeuppipe.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/wakeuppipe.cpp
3 // Purpose: Implementation of wxWakeUpPipe class.
4 // Author: Vadim Zeitlin
5 // Created: 2013-06-09 (extracted from src/unix/evtloopunix.cpp)
6 // Copyright: (c) 2013 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #ifndef WX_PRECOMP
26 #endif // WX_PRECOMP
27
28 #include "wx/unix/private/wakeuppipe.h"
29
30 #include <errno.h>
31
32 // ----------------------------------------------------------------------------
33 // constants
34 // ----------------------------------------------------------------------------
35
36 #define TRACE_EVENTS wxT("events")
37
38 // ============================================================================
39 // wxWakeUpPipe implementation
40 // ============================================================================
41
42 // ----------------------------------------------------------------------------
43 // initialization
44 // ----------------------------------------------------------------------------
45
46 wxWakeUpPipe::wxWakeUpPipe()
47 {
48 m_pipeIsEmpty = true;
49
50 if ( !m_pipe.Create() )
51 {
52 wxLogError(_("Failed to create wake up pipe used by event loop."));
53 return;
54 }
55
56
57 if ( !m_pipe.MakeNonBlocking(wxPipe::Read) )
58 {
59 wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode"));
60 return;
61 }
62
63 wxLogTrace(TRACE_EVENTS, wxT("Wake up pipe (%d, %d) created"),
64 m_pipe[wxPipe::Read], m_pipe[wxPipe::Write]);
65 }
66
67 // ----------------------------------------------------------------------------
68 // wakeup handling
69 // ----------------------------------------------------------------------------
70
71 void wxWakeUpPipe::WakeUpNoLock()
72 {
73 // No need to do anything if the pipe already contains something.
74 if ( !m_pipeIsEmpty )
75 return;
76
77 if ( write(m_pipe[wxPipe::Write], "s", 1) != 1 )
78 {
79 // don't use wxLog here, we can be in another thread and this could
80 // result in dead locks
81 perror("write(wake up pipe)");
82 }
83 else
84 {
85 // We just wrote to it, so it's not empty any more.
86 m_pipeIsEmpty = false;
87 }
88 }
89
90 void wxWakeUpPipe::OnReadWaiting()
91 {
92 // got wakeup from child thread, remove the data that provoked it from the
93 // pipe
94
95 char buf[4];
96 for ( ;; )
97 {
98 const int size = read(GetReadFd(), buf, WXSIZEOF(buf));
99
100 if ( size > 0 )
101 {
102 wxASSERT_MSG( size == 1, "Too many writes to wake-up pipe?" );
103
104 break;
105 }
106
107 if ( size == 0 || (size == -1 && errno == EAGAIN) )
108 {
109 // No data available, not an error (but still surprising,
110 // spurious wakeup?)
111 break;
112 }
113
114 if ( errno == EINTR )
115 {
116 // We were interrupted, try again.
117 continue;
118 }
119
120 wxLogSysError(_("Failed to read from wake-up pipe"));
121
122 return;
123 }
124
125 // The pipe is empty now, so future calls to WakeUp() would need to write
126 // to it again.
127 m_pipeIsEmpty = true;
128 }