129 lines
3.6 KiB
C++
129 lines
3.6 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/unix/wakeuppipe.cpp
|
|
// Purpose: Implementation of wxWakeUpPipe class.
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2013-06-09 (extracted from src/unix/evtloopunix.cpp)
|
|
// Copyright: (c) 2013 Vadim Zeitlin <vadim@wxwidgets.org>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// for compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/unix/private/wakeuppipe.h"
|
|
|
|
#include <errno.h>
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// constants
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define TRACE_EVENTS wxT("events")
|
|
|
|
// ============================================================================
|
|
// wxWakeUpPipe implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// initialization
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxWakeUpPipe::wxWakeUpPipe()
|
|
{
|
|
m_pipeIsEmpty = true;
|
|
|
|
if ( !m_pipe.Create() )
|
|
{
|
|
wxLogError(_("Failed to create wake up pipe used by event loop."));
|
|
return;
|
|
}
|
|
|
|
|
|
if ( !m_pipe.MakeNonBlocking(wxPipe::Read) )
|
|
{
|
|
wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode"));
|
|
return;
|
|
}
|
|
|
|
wxLogTrace(TRACE_EVENTS, wxT("Wake up pipe (%d, %d) created"),
|
|
m_pipe[wxPipe::Read], m_pipe[wxPipe::Write]);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wakeup handling
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxWakeUpPipe::WakeUpNoLock()
|
|
{
|
|
// No need to do anything if the pipe already contains something.
|
|
if ( !m_pipeIsEmpty )
|
|
return;
|
|
|
|
if ( write(m_pipe[wxPipe::Write], "s", 1) != 1 )
|
|
{
|
|
// don't use wxLog here, we can be in another thread and this could
|
|
// result in dead locks
|
|
perror("write(wake up pipe)");
|
|
}
|
|
else
|
|
{
|
|
// We just wrote to it, so it's not empty any more.
|
|
m_pipeIsEmpty = false;
|
|
}
|
|
}
|
|
|
|
void wxWakeUpPipe::OnReadWaiting()
|
|
{
|
|
// got wakeup from child thread, remove the data that provoked it from the
|
|
// pipe
|
|
|
|
char buf[4];
|
|
for ( ;; )
|
|
{
|
|
const int size = read(GetReadFd(), buf, WXSIZEOF(buf));
|
|
|
|
if ( size > 0 )
|
|
{
|
|
wxASSERT_MSG( size == 1, "Too many writes to wake-up pipe?" );
|
|
|
|
break;
|
|
}
|
|
|
|
if ( size == 0 || (size == -1 && errno == EAGAIN) )
|
|
{
|
|
// No data available, not an error (but still surprising,
|
|
// spurious wakeup?)
|
|
break;
|
|
}
|
|
|
|
if ( errno == EINTR )
|
|
{
|
|
// We were interrupted, try again.
|
|
continue;
|
|
}
|
|
|
|
wxLogSysError(_("Failed to read from wake-up pipe"));
|
|
|
|
return;
|
|
}
|
|
|
|
// The pipe is empty now, so future calls to WakeUp() would need to write
|
|
// to it again.
|
|
m_pipeIsEmpty = true;
|
|
}
|