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