/** \file EventHandler.cpp ** \date 2005-12-07 ** \author grymse@alhem.net **/ /* Copyright (C) 2005,2007 Anders Hedstrom This library is made available under the terms of the GNU GPL. If you would like to use this library in a closed-source application, a separate license agreement is available. For information about the closed-source license agreement for the C++ sockets library, please visit http://www.alhem.net/Sockets/license.html and/or email license@alhem.net. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef _MSC_VER #pragma warning(disable:4786) #endif #include "EventHandler.h" #include "IEventOwner.h" #include "Event.h" #include "Socket.h" #include "TcpSocket.h" #include "ListenSocket.h" #ifdef SOCKETS_NAMESPACE namespace SOCKETS_NAMESPACE { #endif EventHandler::EventHandler(StdLog *p) : SocketHandler(p), m_quit(false), m_socket(NULL) { } EventHandler::EventHandler(Mutex& m,StdLog *p) : SocketHandler(m, p), m_quit(false), m_socket(NULL) { } EventHandler::~EventHandler() { while (m_events.size()) { std::list::iterator it = m_events.begin(); Event *e = *it; e -> GetFrom() -> SetHandlerInvalid(); delete e; m_events.erase(it); } } bool EventHandler::GetTimeUntilNextEvent(struct timeval *tv) { if (!m_events.size()) return false; std::list::iterator it = m_events.begin(); if (it != m_events.end()) { EventTime now; mytime_t diff = (*it) -> GetTime() - now; if (diff < 1) { diff = 1; } tv -> tv_sec = static_cast(diff / 1000000); tv -> tv_usec = static_cast(diff % 1000000); return true; } return false; } void EventHandler::CheckEvents() { EventTime now; std::list::iterator it = m_events.begin(); while (it != m_events.end() && (*it) -> GetTime() < now) { Event *e = *it; Socket *s = dynamic_cast(e -> GetFrom()); /* s == NULL This is another object implementing 'IEventOwner' and not a socket. s != NULL This is a Socket implementing IEventOwner, and we can check that the object instance still is valid using SocketHandler::Valid. */ if (!s || (s && Valid(s))) { e -> GetFrom() -> OnEvent(e -> GetID()); } for (it = m_events.begin(); it != m_events.end(); ++it) if (*it == e) break; delete e; if (it != m_events.end()) m_events.erase(it); it = m_events.begin(); } } long EventHandler::AddEvent(IEventOwner *from,long sec,long usec) { Event *e = new Event(from, sec, usec); std::list::iterator it = m_events.begin(); while (it != m_events.end() && *(*it) < *e) { it++; } m_events.insert(it, e); if (m_socket) { m_socket -> Send("\n"); } return e -> GetID(); } void EventHandler::ClearEvents(IEventOwner *from) { bool repeat; do { repeat = false; for (std::list::iterator it = m_events.begin(); it != m_events.end(); it++) { Event *e = *it; if (e -> GetFrom() == from) { delete e; m_events.erase(it); repeat = true; break; } } } while (repeat); } void EventHandler::EventLoop() { while (!m_quit) { struct timeval tv; if (GetTimeUntilNextEvent(&tv)) { Select(&tv); CheckEvents(); } else { Select(); } } } void EventHandler::SetQuit(bool x) { m_quit = x; } void EventHandler::RemoveEvent(IEventOwner *from, long eid) { for (std::list::iterator it = m_events.begin(); it != m_events.end(); it++) { Event *e = *it; if (from == e -> GetFrom() && eid == e -> GetID()) { delete e; m_events.erase(it); break; } } } void EventHandler::Add(Socket *p) { if (!m_socket) { ListenSocket *l = new ListenSocket(*this); l -> SetDeleteByHandler(); l -> Bind("127.0.0.1", 0); m_port = l -> GetPort(); SocketHandler::Add(l); m_socket = new TcpSocket( *this ); m_socket -> SetDeleteByHandler(); m_socket -> SetConnectTimeout(5); m_socket -> SetConnectionRetry(-1); #ifdef ENABLE_RECONNECT m_socket -> SetReconnect(true); #endif m_socket -> Open("127.0.0.1", m_port); SocketHandler::Add(m_socket); } SocketHandler::Add( p ); } #ifdef SOCKETS_NAMESPACE } #endif