Files
wxWidgets/src/unix/epolldispatcher.cpp
Vadim Zeitlin a187327964 Added wxUSE_CONSOLE_EVENTLOOP and wxUSE_SELECT/EPOLLDISPATCHER guards;
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
2007-07-14 19:06:18 +00:00

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