put checks for them in the new Unix-specific wx/unix/chkconf.h file git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47465 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
214 lines
5.6 KiB
C++
214 lines
5.6 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/epolldispatcher.cpp
|
|
// Purpose: implements dispatcher for epoll_wait() call
|
|
// Author: Lukasz Michalski
|
|
// Created: April 2007
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 2007 Lukasz Michalski
|
|
// License: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// for compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef wxUSE_EPOLL_DISPATCHER
|
|
|
|
#include "wx/unix/private/epolldispatcher.h"
|
|
#include "wx/unix/private.h"
|
|
#include "wx/module.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/log.h"
|
|
#include "wx/intl.h"
|
|
#endif
|
|
|
|
#include <sys/epoll.h>
|
|
#include <errno.h>
|
|
|
|
#define wxEpollDispatcher_Trace wxT("epolldispatcher")
|
|
|
|
static wxEpollDispatcher *gs_epollDispatcher = NULL;
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// helper: return EPOLLxxx mask corresponding to the given flags (and also log
|
|
// debugging messages about it)
|
|
static uint32_t GetEpollMask(int flags, int fd)
|
|
{
|
|
uint32_t ep = 0;
|
|
|
|
if ( flags & wxFDIO_INPUT )
|
|
{
|
|
ep |= EPOLLIN;
|
|
wxLogTrace(wxEpollDispatcher_Trace,
|
|
_T("Registered fd %d for input events"), fd);
|
|
}
|
|
|
|
if ( flags & wxFDIO_OUTPUT )
|
|
{
|
|
ep |= EPOLLOUT;
|
|
wxLogTrace(wxEpollDispatcher_Trace,
|
|
_T("Registered fd %d for output events"), fd);
|
|
}
|
|
|
|
if ( flags & wxFDIO_EXCEPTION )
|
|
{
|
|
ep |= EPOLLERR | EPOLLHUP;
|
|
wxLogTrace(wxEpollDispatcher_Trace,
|
|
_T("Registered fd %d for exceptional events"), fd);
|
|
}
|
|
|
|
return ep;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxEpollDispatcher
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxEpollDispatcher::wxEpollDispatcher()
|
|
{
|
|
m_epollDescriptor = epoll_create(1024);
|
|
if ( m_epollDescriptor == -1 )
|
|
{
|
|
wxLogSysError(_("Failed to create epoll descriptor"));
|
|
}
|
|
}
|
|
|
|
bool wxEpollDispatcher::RegisterFD(int fd, wxFDIOHandler* handler, int flags)
|
|
{
|
|
epoll_event ev;
|
|
ev.events = GetEpollMask(flags, fd);
|
|
ev.data.ptr = handler;
|
|
|
|
const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_ADD, fd, &ev);
|
|
if ( ret != 0 )
|
|
{
|
|
wxLogSysError(_("Failed to add descriptor %d to epoll descriptor %d"),
|
|
fd, m_epollDescriptor);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool wxEpollDispatcher::ModifyFD(int fd, wxFDIOHandler* handler, int flags)
|
|
{
|
|
epoll_event ev;
|
|
ev.events = GetEpollMask(flags, fd);
|
|
ev.data.ptr = handler;
|
|
|
|
const int ret = epoll_ctl(m_epollDescriptor, EPOLL_CTL_MOD, fd, &ev);
|
|
if ( ret != 0 )
|
|
{
|
|
wxLogSysError(_("Failed to modify descriptor %d in epoll descriptor %d"),
|
|
fd, m_epollDescriptor);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool wxEpollDispatcher::UnregisterFD(int fd, int flags)
|
|
{
|
|
epoll_event ev;
|
|
ev.events = 0;
|
|
ev.data.ptr = NULL;
|
|
|
|
if ( epoll_ctl(m_epollDescriptor, EPOLL_CTL_DEL, fd, &ev) != 0 )
|
|
{
|
|
wxLogSysError(_("Failed to unregister descriptor %d from epoll descriptor %d"),
|
|
fd, m_epollDescriptor);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void wxEpollDispatcher::RunLoop(int timeout)
|
|
{
|
|
epoll_event events[16];
|
|
|
|
const int e_num = epoll_wait
|
|
(
|
|
m_epollDescriptor,
|
|
events,
|
|
WXSIZEOF(events),
|
|
timeout == TIMEOUT_INFINITE ? -1 : timeout
|
|
);
|
|
|
|
if ( e_num == -1 )
|
|
{
|
|
if ( errno != EINTR )
|
|
{
|
|
wxLogSysError(_("Waiting for IO on epoll descriptor %d failed"),
|
|
m_epollDescriptor);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for ( epoll_event *p = events; p < events + e_num; p++ )
|
|
{
|
|
wxFDIOHandler * const handler = (wxFDIOHandler *)(p->data.ptr);
|
|
if ( !handler )
|
|
{
|
|
wxFAIL_MSG( _T("NULL handler in epoll_event?") );
|
|
continue;
|
|
}
|
|
|
|
if ( p->events & EPOLLIN )
|
|
handler->OnReadWaiting();
|
|
|
|
if ( p->events & EPOLLOUT )
|
|
handler->OnWriteWaiting();
|
|
|
|
if ( p->events & (EPOLLERR | EPOLLHUP) )
|
|
handler->OnExceptionWaiting();
|
|
}
|
|
}
|
|
|
|
/* static */
|
|
wxEpollDispatcher *wxEpollDispatcher::Get()
|
|
{
|
|
if ( !gs_epollDispatcher )
|
|
{
|
|
gs_epollDispatcher = new wxEpollDispatcher;
|
|
if ( !gs_epollDispatcher->IsOk() )
|
|
{
|
|
delete gs_epollDispatcher;
|
|
gs_epollDispatcher = NULL;
|
|
}
|
|
}
|
|
|
|
return gs_epollDispatcher;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxEpollDispatcherModule
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxEpollDispatcherModule : public wxModule
|
|
{
|
|
public:
|
|
wxEpollDispatcherModule() { }
|
|
|
|
virtual bool OnInit() { return true; }
|
|
virtual void OnExit() { wxDELETE(gs_epollDispatcher); }
|
|
|
|
DECLARE_DYNAMIC_CLASS(wxEpollDispatcherModule)
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxEpollDispatcherModule, wxModule)
|
|
|
|
#endif // wxUSE_EPOLL_DISPATCHER
|