version 3.0
This commit is contained in:
commit
d837490606
209 changed files with 19662 additions and 0 deletions
0
event/Makefile
Normal file
0
event/Makefile
Normal file
91
event/action.h
Normal file
91
event/action.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_ACTION_H
|
||||
#define EVENT_ACTION_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: action.h //
|
||||
// Description: basic classes for event callback management //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Action
|
||||
{
|
||||
protected:
|
||||
bool cancelled_;
|
||||
|
||||
Action () : cancelled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Action ()
|
||||
{
|
||||
ASSERT("/action", cancelled_);
|
||||
}
|
||||
|
||||
virtual void cancel () = 0;
|
||||
|
||||
bool is_cancelled ()
|
||||
{
|
||||
return cancelled_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class S, class C> class CallbackAction : public Action
|
||||
{
|
||||
typedef void (S::*const method_t)(void);
|
||||
|
||||
public:
|
||||
S* const obj_;
|
||||
method_t method_;
|
||||
C* callback_;
|
||||
|
||||
public:
|
||||
CallbackAction (S* obj, method_t method, C* cb) : obj_(obj), method_(method)
|
||||
{
|
||||
ASSERT("/action", obj && method);
|
||||
callback_ = cb;
|
||||
}
|
||||
|
||||
~CallbackAction()
|
||||
{
|
||||
delete callback_;
|
||||
}
|
||||
|
||||
virtual void cancel ()
|
||||
{
|
||||
cancelled_ = true;
|
||||
(obj_->*method_) ();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !EVENT_ACTION_H */
|
46
event/callback.h
Normal file
46
event/callback.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_CALLBACK_H
|
||||
#define EVENT_CALLBACK_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: callback.h //
|
||||
// Description: base class for event callback specializations //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Callback
|
||||
{
|
||||
public:
|
||||
virtual ~Callback () {}
|
||||
virtual void execute () = 0;
|
||||
};
|
||||
|
||||
#endif /* !EVENT_CALLBACK_H */
|
150
event/callback_queue.h
Normal file
150
event/callback_queue.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_CALLBACK_QUEUE_H
|
||||
#define EVENT_CALLBACK_QUEUE_H
|
||||
|
||||
#include <deque>
|
||||
#include <event/callback.h>
|
||||
#include <event/action.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: callback_queue.h //
|
||||
// Description: collection classes for event callback management //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CallbackQueue
|
||||
{
|
||||
class QueuedAction : public Action
|
||||
{
|
||||
CallbackQueue& queue_;
|
||||
uint64_t generation_;
|
||||
Callback* callback_;
|
||||
|
||||
public:
|
||||
QueuedAction (CallbackQueue& q, uint64_t g, Callback* cb)
|
||||
: queue_(q),
|
||||
generation_(g),
|
||||
callback_(cb)
|
||||
{
|
||||
}
|
||||
|
||||
~QueuedAction ()
|
||||
{
|
||||
delete callback_;
|
||||
}
|
||||
|
||||
virtual void cancel ()
|
||||
{
|
||||
cancelled_ = true;
|
||||
queue_.cancel (this);
|
||||
}
|
||||
|
||||
friend class CallbackQueue;
|
||||
};
|
||||
|
||||
std::deque<QueuedAction*> queue_;
|
||||
uint64_t generation_;
|
||||
|
||||
public:
|
||||
CallbackQueue ()
|
||||
: queue_(),
|
||||
generation_(0)
|
||||
{ }
|
||||
|
||||
~CallbackQueue ()
|
||||
{
|
||||
std::deque<QueuedAction*>::iterator it;
|
||||
for (it = queue_.begin (); it != queue_.end (); ++it)
|
||||
{
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Action* schedule (Callback* cb)
|
||||
{
|
||||
QueuedAction* a = new QueuedAction (*this, generation_, cb);
|
||||
queue_.push_back (a);
|
||||
return (a);
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs all callbacks that have already been queued, but none that
|
||||
* are added by callbacks that are called as part of the drain
|
||||
* operation. Returns true if there are queued callbacks that were
|
||||
* added during drain.
|
||||
*/
|
||||
bool drain (void)
|
||||
{
|
||||
generation_++;
|
||||
while (! queue_.empty ())
|
||||
{
|
||||
QueuedAction* a = queue_.front ();
|
||||
if (a->generation_ >= generation_)
|
||||
return (true);
|
||||
queue_.pop_front ();
|
||||
if (a->callback_)
|
||||
a->callback_->execute ();
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return (queue_.empty ());
|
||||
}
|
||||
|
||||
void perform ()
|
||||
{
|
||||
if (! queue_.empty ())
|
||||
{
|
||||
QueuedAction* a = queue_.front ();
|
||||
if (a->callback_)
|
||||
a->callback_->execute ();
|
||||
}
|
||||
}
|
||||
|
||||
void cancel (QueuedAction* a)
|
||||
{
|
||||
std::deque<QueuedAction*>::iterator it;
|
||||
for (it = queue_.begin (); it != queue_.end (); ++it)
|
||||
{
|
||||
if (*it == a)
|
||||
{
|
||||
queue_.erase (it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete a;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !EVENT_CALLBACK_QUEUE_H */
|
136
event/event.h
Normal file
136
event/event.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_EVENT_H
|
||||
#define EVENT_EVENT_H
|
||||
|
||||
#include <common/buffer.h>
|
||||
|
||||
/*
|
||||
* The general-purpose event type. Never extended or anything like that.
|
||||
* Tracking a user-specified pointer is handled by the callback, providers of
|
||||
* Events can pass extra data by extending their Callback type, e.g. the
|
||||
* SocketEventCallback used by Socket::accept() to pass back a Socket pointer
|
||||
* along with an Event.
|
||||
* XXX In light of this extension, it may make sense to move the Buffer out
|
||||
* of Event now, since the Callback can handle Buffers independently.
|
||||
*
|
||||
* Because we are primarily a data-movement/processing system, a Buffer is an
|
||||
* integral part of every Event. Plus, Buffers with no data are basically
|
||||
* free to copy, etc.
|
||||
*
|
||||
* Event handlers/callbacks always take a copy of the Event, which is subpar
|
||||
* but necessary since the first thing most of those callbacks do is to cancel
|
||||
* the Action that called them, which in turn deletes the underlying SimpleCallback
|
||||
* object, which would in turn delete the holder of the associated Event if a
|
||||
* reference or pointer were passed. One can argue that the right thing to do
|
||||
* is process the event fully before cancelling the Action, but that is not
|
||||
* how things are done at present.
|
||||
*/
|
||||
struct Event {
|
||||
enum Type {
|
||||
Invalid,
|
||||
Done,
|
||||
EOS,
|
||||
Error,
|
||||
};
|
||||
|
||||
Type type_;
|
||||
int error_;
|
||||
Buffer buffer_;
|
||||
|
||||
Event(void)
|
||||
: type_(Event::Invalid),
|
||||
error_(0),
|
||||
buffer_()
|
||||
{ }
|
||||
|
||||
Event(Type type)
|
||||
: type_(type),
|
||||
error_(0),
|
||||
buffer_()
|
||||
{ }
|
||||
|
||||
Event(Type type, int error)
|
||||
: type_(type),
|
||||
error_(error),
|
||||
buffer_()
|
||||
{ }
|
||||
|
||||
|
||||
Event(Type type, const Buffer& buffer)
|
||||
: type_(type),
|
||||
error_(0),
|
||||
buffer_(buffer)
|
||||
{ }
|
||||
|
||||
Event(Type type, int error, const Buffer& buffer)
|
||||
: type_(type),
|
||||
error_(error),
|
||||
buffer_(buffer)
|
||||
{ }
|
||||
|
||||
Event(const Event& e)
|
||||
: type_(e.type_),
|
||||
error_(e.error_),
|
||||
buffer_(e.buffer_)
|
||||
{ }
|
||||
|
||||
Event& operator= (const Event& e)
|
||||
{
|
||||
type_ = e.type_;
|
||||
error_ = e.error_;
|
||||
buffer_ = e.buffer_;
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
static inline std::ostream&
|
||||
operator<< (std::ostream& os, Event::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Event::Invalid:
|
||||
return (os << "<Invalid>");
|
||||
case Event::Done:
|
||||
return (os << "<Done>");
|
||||
case Event::EOS:
|
||||
return (os << "<EOS>");
|
||||
case Event::Error:
|
||||
return (os << "<Error>");
|
||||
default:
|
||||
return (os << "<Unexpected Event::Type>");
|
||||
}
|
||||
}
|
||||
|
||||
static inline std::ostream&
|
||||
operator<< (std::ostream& os, Event e)
|
||||
{
|
||||
if (e.type_ != Event::Error && e.error_ == 0)
|
||||
return (os << e.type_);
|
||||
return (os << e.type_ << '/' << e.error_ << " [" <<
|
||||
strerror(e.error_) << "]");
|
||||
}
|
||||
|
||||
#endif /* !EVENT_EVENT_H */
|
34
event/event_callback.h
Normal file
34
event/event_callback.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_EVENT_CALLBACK_H
|
||||
#define EVENT_EVENT_CALLBACK_H
|
||||
|
||||
#include <event/event.h>
|
||||
#include <event/typed_callback.h>
|
||||
|
||||
typedef class TypedCallback<Event> EventCallback;
|
||||
|
||||
#endif /* !EVENT_EVENT_CALLBACK_H */
|
22
event/event_message.h
Normal file
22
event/event_message.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_message.h //
|
||||
// Description: sructures for data exchange in shared buffers //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EVENT_EVENT_MESSAGE_H
|
||||
#define EVENT_EVENT_MESSAGE_H
|
||||
|
||||
class EventAction;
|
||||
|
||||
struct EventMessage
|
||||
{
|
||||
int op;
|
||||
EventAction* action;
|
||||
};
|
||||
|
||||
#endif /* !EVENT_EVENT_MESSAGE_H */
|
152
event/event_poll_epoll.cc
Normal file
152
event/event_poll_epoll.cc
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_poll_epoll.cc //
|
||||
// Description: IO event handling using Linux epoll functions //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IoService::open_resources ()
|
||||
{
|
||||
handle_ = ::epoll_create (IO_POLL_EVENT_COUNT);
|
||||
ASSERT(log_, handle_ != -1);
|
||||
}
|
||||
|
||||
void IoService::close_resources ()
|
||||
{
|
||||
if (handle_ >= 0)
|
||||
::close (handle_);
|
||||
}
|
||||
|
||||
void IoService::set_fd (int fd, int rd, int wr, IoNode* node)
|
||||
{
|
||||
struct epoll_event eev;
|
||||
int rv;
|
||||
eev.events = ((rd > 0 ? EPOLLIN : 0) | (wr > 0 ? EPOLLOUT : 0));
|
||||
eev.data.ptr = node;
|
||||
if (eev.events)
|
||||
rv = ::epoll_ctl (handle_, (rd && wr ? EPOLL_CTL_MOD : EPOLL_CTL_ADD), fd, &eev);
|
||||
else
|
||||
rv = ::epoll_ctl (handle_, EPOLL_CTL_DEL, fd, &eev);
|
||||
if (rv < 0 && errno != EEXIST && errno != ENOENT)
|
||||
CRITICAL(log_) << "Could not add event to epoll.";
|
||||
}
|
||||
|
||||
void IoService::poll (int ms)
|
||||
{
|
||||
struct epoll_event eev[IO_POLL_EVENT_COUNT];
|
||||
int evcnt;
|
||||
|
||||
evcnt = ::epoll_wait (handle_, eev, IO_POLL_EVENT_COUNT, ms);
|
||||
if (evcnt < 0 && errno != EINTR)
|
||||
CRITICAL(log_) << "Could not poll epoll.";
|
||||
|
||||
for (int i = 0; i < evcnt; ++i)
|
||||
{
|
||||
int flg = eev[i].events;
|
||||
IoNode* node = (IoNode*) eev[i].data.ptr;
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if ((flg & EPOLLIN))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeAccept && (ev.type_ = Event::Done)) || read_channel (node->fd, ev, 1))
|
||||
{
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (node->fd, -1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
}
|
||||
else if (node)
|
||||
read_channel (node->fd, ok, 0);
|
||||
}
|
||||
|
||||
if ((flg & EPOLLOUT))
|
||||
{
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeConnect && (ev.type_ = Event::Done)) ||
|
||||
(act->mode_ == StreamModeWrite && write_channel (node->fd, ev)) ||
|
||||
(act->mode_ == StreamModeEnd && close_channel (node->fd, ev)))
|
||||
{
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
set_fd (node->fd, (node->reading ? 2 : 0), -1, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! (flg & (EPOLLIN | EPOLLOUT)))
|
||||
{
|
||||
if ((flg & EPOLLERR))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (node->fd, -1, 0, node);
|
||||
}
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
set_fd (node->fd, 0, -1, node);
|
||||
}
|
||||
}
|
||||
else if ((flg & EPOLLHUP))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::EOS;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (node->fd, -1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
159
event/event_poll_kqueue.cc
Normal file
159
event/event_poll_kqueue.cc
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_poll_kqueue.cc //
|
||||
// Description: IO event handling using FreeBSD kevent functions //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IoService::open_resources ()
|
||||
{
|
||||
handle_ = kqueue ();
|
||||
ASSERT(log_, handle_ != -1);
|
||||
}
|
||||
|
||||
void IoService::close_resources ()
|
||||
{
|
||||
if (handle_ >= 0)
|
||||
::close (handle_);
|
||||
}
|
||||
|
||||
void IoService::set_fd (int fd, int rd, int wr, IoNode* node)
|
||||
{
|
||||
struct kevent kev;
|
||||
int rv;
|
||||
if (rd == 1)
|
||||
EV_SET (&kev, fd, EVFILT_READ, EV_ADD, 0, 0, node);
|
||||
else if (wr == 1)
|
||||
EV_SET (&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, node);
|
||||
else if (rd == -1)
|
||||
EV_SET (&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, node);
|
||||
else if (wr == -1)
|
||||
EV_SET (&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, node);
|
||||
rv = ::kevent (handle_, &kev, 1, 0, 0, 0);
|
||||
if (rv < 0 && errno != EEXIST && errno != ENOENT)
|
||||
CRITICAL(log_) << "Could not add event to kqueue.";
|
||||
}
|
||||
|
||||
void IoService::poll (int ms)
|
||||
{
|
||||
struct kevent kev[IO_POLL_EVENT_COUNT];
|
||||
struct timespec ts;
|
||||
int evcnt;
|
||||
|
||||
if (ms != -1)
|
||||
{
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000000;
|
||||
}
|
||||
|
||||
evcnt = ::kevent (handle_, 0, 0, kev, IO_POLL_EVENT_COUNT, (ms == -1 ? 0 : &ts));
|
||||
if (evcnt < 0 && errno != EINTR)
|
||||
CRITICAL(log_) << "Could not poll kqueue.";
|
||||
|
||||
for (int i = 0; i < evcnt; i++)
|
||||
{
|
||||
int sck = kev[i].ident;
|
||||
int flt = kev[i].filter;
|
||||
int flg = kev[i].flags;
|
||||
IoNode* node = (IoNode*) kev[i].udata;
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if ((flg & EV_ERROR))
|
||||
{
|
||||
if (flt == EVFILT_READ && node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (sck, -1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
else if (flt == EVFILT_WRITE && node && (act = node->write_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
set_fd (sck, (node->reading ? 2 : 0), -1, node);
|
||||
}
|
||||
}
|
||||
else if ((flg & EV_EOF))
|
||||
{
|
||||
if (flt == EVFILT_READ && node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::EOS;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (sck, -1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
}
|
||||
else if ((flt == EVFILT_READ))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeAccept && (ev.type_ = Event::Done)) || read_channel (sck, ev, 1))
|
||||
{
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
set_fd (sck, -1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
}
|
||||
else if (node)
|
||||
read_channel (sck, ok, 0);
|
||||
}
|
||||
else if ((flt == EVFILT_WRITE))
|
||||
{
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeConnect && (ev.type_ = Event::Done)) ||
|
||||
(act->mode_ == StreamModeWrite && write_channel (sck, ev)) ||
|
||||
(act->mode_ == StreamModeEnd && close_channel (sck, ev)))
|
||||
{
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
set_fd (sck, (node->reading ? 2 : 0), -1, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
157
event/event_poll_poll.cc
Normal file
157
event/event_poll_poll.cc
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_poll_poll.cc //
|
||||
// Description: IO event handling using standard poll functions //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IoService::open_resources ()
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::close_resources ()
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::set_fd (int fd, int rd, int wr, IoNode* node)
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::poll (int ms)
|
||||
{
|
||||
struct pollfd fds[fd_map_.size () + 1];
|
||||
int i, j, f;
|
||||
int cnt;
|
||||
|
||||
fds[0].fd = rfd_;
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].revents = 0;
|
||||
j = 1;
|
||||
|
||||
std::map<int, IoNode>::iterator it;
|
||||
for (it = fd_map_.begin (); it != fd_map_.end (); ++it)
|
||||
{
|
||||
if ((f = (it->second.reading ? POLLIN : 0) | (it->second.writing ? POLLOUT : 0)))
|
||||
{
|
||||
fds[j].fd = it->first;
|
||||
fds[j].events = f;
|
||||
fds[j].revents = 0;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
cnt = ::poll (fds, j, ms);
|
||||
if (cnt < 0 && errno != EINTR)
|
||||
CRITICAL(log_) << "Could not poll.";
|
||||
|
||||
for (i = 0; i < j; ++i)
|
||||
{
|
||||
if (fds[i].revents == 0)
|
||||
continue;
|
||||
if (cnt-- == 0)
|
||||
break;
|
||||
|
||||
int sck = fds[i].fd;
|
||||
int flg = fds[i].revents;
|
||||
it = fd_map_.find (sck);
|
||||
IoNode* node = (it != fd_map_.end () ? &it->second : 0);
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if ((flg & POLLIN))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeAccept && (ev.type_ = Event::Done)) || read_channel (sck, ev, 1))
|
||||
{
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
}
|
||||
else if (node)
|
||||
read_channel (sck, ok, 0);
|
||||
}
|
||||
|
||||
if ((flg & POLLOUT))
|
||||
{
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeConnect && (ev.type_ = Event::Done)) ||
|
||||
(act->mode_ == StreamModeWrite && write_channel (sck, ev)) ||
|
||||
(act->mode_ == StreamModeEnd && close_channel (sck, ev)))
|
||||
{
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! (flg & (POLLIN | POLLOUT)))
|
||||
{
|
||||
if ((flg & (POLLERR | POLLNVAL)))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
}
|
||||
}
|
||||
else if ((flg & POLLHUP))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::EOS;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
event/event_poll_port.cc
Normal file
174
event/event_poll_port.cc
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <port.h>
|
||||
#include <unistd.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_poll_port.cc //
|
||||
// Description: IO event handling using SunOS port functions //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IoService::open_resources ()
|
||||
{
|
||||
handle_ = port_create ();
|
||||
ASSERT(log_, handle_ != -1);
|
||||
}
|
||||
|
||||
void IoService::close_resources ()
|
||||
{
|
||||
if (handle_ >= 0)
|
||||
::close (handle_);
|
||||
}
|
||||
|
||||
void IoService::set_fd (int fd, int rd, int wr, IoNode* node)
|
||||
{
|
||||
int events;
|
||||
int rv;
|
||||
events = ((rd > 0 ? EPOLLIN : 0) | (wr > 0 ? EPOLLOUT : 0));
|
||||
if (events)
|
||||
{
|
||||
rv = ::port_associate (handle_, PORT_SOURCE_FD, fd, events, node);
|
||||
if (rv < 0 && errno != EEXIST)
|
||||
CRITICAL(log_) << "Could not add event to port.";
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = ::port_dissociate (handle_, PORT_SOURCE_FD, fd);
|
||||
if (rv < 0 && errno != ENOENT)
|
||||
CRITICAL(log_) << "Could not add event to port.";
|
||||
}
|
||||
}
|
||||
|
||||
void IoService::poll (int ms)
|
||||
{
|
||||
port_event_t pev[IO_POLL_EVENT_COUNT];
|
||||
unsigned int evcnt = 1;
|
||||
struct timespec ts;
|
||||
int rv;
|
||||
|
||||
if (ms != -1)
|
||||
{
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000000;
|
||||
}
|
||||
|
||||
rv = ::port_getn (handle_, pev, IO_POLL_EVENT_COUNT, &evcnt, (ms == -1 ? 0 : &ts));
|
||||
if (rv < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
CRITICAL(log_) << "Could not poll port.";
|
||||
evcnt = 0;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < evcnt; ++i)
|
||||
{
|
||||
int sck = pev[i].portev_object;
|
||||
int flg = pev[i].portev_events;
|
||||
IoNode* node = (IoNode*) pev[i].portev_user;
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if ((flg & POLLIN))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeAccept && (ev.type_ = Event::Done)) || read_channel (sck, ev, 1))
|
||||
{
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
else
|
||||
set_fd (sck, 1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
else if (node)
|
||||
{
|
||||
read_channel (sck, ok, 0);
|
||||
set_fd (sck, 1, (node->writing ? 2 : 0), node);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flg & POLLOUT))
|
||||
{
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeConnect && (ev.type_ = Event::Done)) ||
|
||||
(act->mode_ == StreamModeWrite && write_channel (sck, ev)) ||
|
||||
(act->mode_ == StreamModeEnd && close_channel (sck, ev)))
|
||||
{
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
}
|
||||
else
|
||||
set_fd (sck, (node->reading ? 2 : 0), 1, node);
|
||||
}
|
||||
}
|
||||
|
||||
if (! (flg & (POLLIN | POLLOUT)))
|
||||
{
|
||||
if ((flg & POLLERR))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
}
|
||||
}
|
||||
else if ((flg & POLLHUP))
|
||||
{
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
if (act->callback_)
|
||||
act->callback_->param ().type_ = Event::EOS;
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
138
event/event_poll_select.cc
Normal file
138
event/event_poll_select.cc
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_poll_select.cc //
|
||||
// Description: IO event handling using traditional select calls //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IoService::open_resources ()
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::close_resources ()
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::set_fd (int fd, int rd, int wr, IoNode* node)
|
||||
{
|
||||
}
|
||||
|
||||
void IoService::poll (int ms)
|
||||
{
|
||||
fd_set read_set, write_set;
|
||||
struct timeval tv;
|
||||
int maxfd;
|
||||
int fdcnt;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
FD_ZERO(&write_set);
|
||||
FD_SET(rfd_, &read_set);
|
||||
maxfd = rfd_;
|
||||
|
||||
std::map<int, IoNode>::iterator it;
|
||||
for (it = fd_map_.begin (); it != fd_map_.end (); ++it)
|
||||
{
|
||||
if (it->second.reading)
|
||||
FD_SET (it->first, &read_set);
|
||||
if (it->second.writing)
|
||||
FD_SET (it->first, &write_set);
|
||||
if (maxfd < it->first)
|
||||
maxfd = it->first;
|
||||
}
|
||||
|
||||
ASSERT(log_, maxfd != -1);
|
||||
|
||||
if (ms != -1)
|
||||
{
|
||||
tv.tv_sec = ms / 1000;
|
||||
tv.tv_usec = ms % 1000;
|
||||
}
|
||||
|
||||
fdcnt = ::select (maxfd + 1, &read_set, &write_set, 0, (ms == -1 ? 0 : &tv));
|
||||
if (fdcnt < 0 && errno != EINTR)
|
||||
CRITICAL(log_) << "Could not poll select.";
|
||||
|
||||
for (int sck = 0; sck <= maxfd && fdcnt > 0; ++sck)
|
||||
{
|
||||
if (FD_ISSET (sck, &read_set))
|
||||
{
|
||||
it = fd_map_.find (sck);
|
||||
IoNode* node = (it != fd_map_.end () ? &it->second : 0);
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if (node && (act = node->read_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeAccept && (ev.type_ = Event::Done)) || read_channel (sck, ev, 1))
|
||||
{
|
||||
schedule (act);
|
||||
node->reading = false;
|
||||
}
|
||||
}
|
||||
else if (node)
|
||||
read_channel (sck, ok, 0);
|
||||
|
||||
ASSERT(log_, fdcnt > 0);
|
||||
fdcnt--;
|
||||
}
|
||||
|
||||
if (FD_ISSET (sck, &write_set))
|
||||
{
|
||||
it = fd_map_.find (sck);
|
||||
IoNode* node = (it != fd_map_.end () ? &it->second : 0);
|
||||
EventAction* act;
|
||||
Event ok;
|
||||
|
||||
if (node && (act = node->write_action))
|
||||
{
|
||||
Event& ev = (act->callback_ ? act->callback_->param () : ok);
|
||||
if ((act->mode_ == StreamModeConnect && (ev.type_ = Event::Done)) ||
|
||||
(act->mode_ == StreamModeWrite && write_channel (sck, ev)) ||
|
||||
(act->mode_ == StreamModeEnd && close_channel (sck, ev)))
|
||||
{
|
||||
schedule (act);
|
||||
node->writing = false;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(log_, fdcnt > 0);
|
||||
fdcnt--;
|
||||
}
|
||||
}
|
||||
}
|
133
event/event_system.cc
Normal file
133
event/event_system.cc
Normal file
|
@ -0,0 +1,133 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_system.cc //
|
||||
// Description: global event handling core class implementation //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include <event/event_system.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
static void signal_reload (int) { event_system.reload (); }
|
||||
static void signal_stop (int) { event_system.stop (); }
|
||||
}
|
||||
|
||||
EventSystem::EventSystem () : log_ ("/event/system"), reload_ (false), stop_ (false)
|
||||
{
|
||||
::signal (SIGHUP, signal_reload);
|
||||
::signal (SIGINT, signal_stop);
|
||||
::signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
struct rlimit rlim;
|
||||
int rv = ::getrlimit (RLIMIT_NOFILE, &rlim);
|
||||
if (rv == 0 && rlim.rlim_cur < rlim.rlim_max)
|
||||
{
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
rv = ::setrlimit (RLIMIT_NOFILE, &rlim);
|
||||
}
|
||||
}
|
||||
|
||||
void EventSystem::run ()
|
||||
{
|
||||
EventMessage msg;
|
||||
|
||||
INFO(log_) << "Starting event system.";
|
||||
|
||||
io_service_.start ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (gateway_.read (msg))
|
||||
{
|
||||
if (msg.op >= 0)
|
||||
{
|
||||
if (msg.action && ! msg.action->is_cancelled ())
|
||||
{
|
||||
if (msg.action->callback_)
|
||||
msg.action->callback_->execute ();
|
||||
else
|
||||
msg.action->cancel ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete msg.action;
|
||||
}
|
||||
}
|
||||
|
||||
if (reload_)
|
||||
{
|
||||
if (! interest_queue_[EventInterestReload].empty ())
|
||||
{
|
||||
INFO(log_) << "Running reload handlers.";
|
||||
interest_queue_[EventInterestReload].drain ();
|
||||
INFO(log_) << "Reload handlers have been run.";
|
||||
}
|
||||
reload_ = false;
|
||||
::signal (SIGHUP, signal_reload);
|
||||
}
|
||||
|
||||
if (stop_)
|
||||
{
|
||||
if (! interest_queue_[EventInterestStop].empty ())
|
||||
{
|
||||
INFO(log_) << "Running stop handlers.";
|
||||
interest_queue_[EventInterestStop].drain ();
|
||||
INFO(log_) << "Stop handlers have been run.";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
io_service_.stop ();
|
||||
}
|
||||
|
||||
void EventSystem::reload ()
|
||||
{
|
||||
::signal (SIGHUP, SIG_IGN);
|
||||
reload_ = true;
|
||||
gateway_.wakeup ();
|
||||
}
|
||||
|
||||
void EventSystem::stop ()
|
||||
{
|
||||
::signal (SIGINT, SIG_IGN);
|
||||
stop_ = true;
|
||||
gateway_.wakeup ();
|
||||
}
|
||||
|
||||
Action* EventSystem::register_interest (EventInterest interest, Callback* cb)
|
||||
{
|
||||
return interest_queue_[interest].schedule (cb);
|
||||
}
|
||||
|
||||
Action* EventSystem::track (int fd, StreamMode mode, EventCallback* cb)
|
||||
{
|
||||
EventAction* act;
|
||||
|
||||
if ((act = new EventAction (*this, fd, mode, cb)))
|
||||
{
|
||||
EventMessage msg = {1, act};
|
||||
io_service_.take_message (msg);
|
||||
}
|
||||
|
||||
return (cb ? act : 0);
|
||||
}
|
||||
|
||||
void EventSystem::cancel (EventAction* act)
|
||||
{
|
||||
if (act)
|
||||
{
|
||||
EventMessage msg = {-1, act};
|
||||
io_service_.take_message (msg);
|
||||
}
|
||||
}
|
||||
|
||||
EventSystem event_system;
|
92
event/event_system.h
Normal file
92
event/event_system.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: event_system.h //
|
||||
// Description: global event handling core class definition //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EVENT_EVENT_SYSTEM_H
|
||||
#define EVENT_EVENT_SYSTEM_H
|
||||
|
||||
#include <common/buffer.h>
|
||||
#include <common/ring_buffer.h>
|
||||
#include <event/action.h>
|
||||
#include <event/event_callback.h>
|
||||
#include <event/object_callback.h>
|
||||
#include <event/callback_queue.h>
|
||||
#include <event/event_message.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
class EventAction;
|
||||
|
||||
enum EventInterest
|
||||
{
|
||||
EventInterestReload,
|
||||
EventInterestStop,
|
||||
EventInterests
|
||||
};
|
||||
|
||||
enum StreamMode
|
||||
{
|
||||
StreamModeConnect,
|
||||
StreamModeAccept,
|
||||
StreamModeRead,
|
||||
StreamModeWrite,
|
||||
StreamModeEnd
|
||||
};
|
||||
|
||||
class EventSystem
|
||||
{
|
||||
private:
|
||||
LogHandle log_;
|
||||
IoService io_service_;
|
||||
WaitBuffer<EventMessage> gateway_;
|
||||
CallbackQueue interest_queue_[EventInterests];
|
||||
bool reload_, stop_;
|
||||
|
||||
public:
|
||||
EventSystem ();
|
||||
|
||||
void run ();
|
||||
void reload ();
|
||||
void stop ();
|
||||
|
||||
Action* register_interest (EventInterest interest, Callback* cb);
|
||||
Action* track (int fd, StreamMode mode, EventCallback* cb);
|
||||
void cancel (EventAction* act);
|
||||
|
||||
int take_message (const EventMessage& msg) { return gateway_.write (msg); }
|
||||
};
|
||||
|
||||
class EventAction : public Action
|
||||
{
|
||||
public:
|
||||
EventSystem& system_;
|
||||
int fd_;
|
||||
StreamMode mode_;
|
||||
EventCallback* callback_;
|
||||
|
||||
public:
|
||||
EventAction (EventSystem& sys, int fd, StreamMode mode, EventCallback* cb) : system_ (sys)
|
||||
{
|
||||
fd_ = fd; mode_ = mode; callback_ = cb;
|
||||
}
|
||||
|
||||
~EventAction ()
|
||||
{
|
||||
delete callback_;
|
||||
}
|
||||
|
||||
virtual void cancel ()
|
||||
{
|
||||
cancelled_ = true;
|
||||
system_.cancel (this);
|
||||
}
|
||||
};
|
||||
|
||||
extern EventSystem event_system;
|
||||
|
||||
#endif /* !EVENT_EVENT_SYSTEM_H */
|
329
event/io_service.cc
Normal file
329
event/io_service.cc
Normal file
|
@ -0,0 +1,329 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: io_service.h //
|
||||
// Description: servicing of network IO requests for the event system //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <limits.h>
|
||||
#include <event/event_system.h>
|
||||
#include <event/io_service.h>
|
||||
|
||||
IoService::IoService () : Thread ("IoService"), log_ ("/io/thread")
|
||||
{
|
||||
handle_ = rfd_ = wfd_ = -1;
|
||||
|
||||
int fd[2];
|
||||
if (::pipe (fd) == 0)
|
||||
rfd_ = fd[0], wfd_ = fd[1];
|
||||
}
|
||||
|
||||
IoService::~IoService ()
|
||||
{
|
||||
if (rfd_ >= 0)
|
||||
::close (rfd_);
|
||||
if (wfd_ >= 0)
|
||||
::close (wfd_);
|
||||
}
|
||||
|
||||
void IoService::main ()
|
||||
{
|
||||
EventMessage msg;
|
||||
|
||||
INFO(log_) << "Starting IO thread.";
|
||||
|
||||
open_resources ();
|
||||
IoNode node = {rfd_, true, false, 0, 0};
|
||||
set_fd (rfd_, 1, 0, &node);
|
||||
|
||||
while (! stop_)
|
||||
{
|
||||
while (gateway_.read (msg))
|
||||
{
|
||||
if (msg.op >= 0)
|
||||
handle_request (msg.action);
|
||||
else
|
||||
cancel (msg.action);
|
||||
}
|
||||
|
||||
poll (-1);
|
||||
}
|
||||
|
||||
set_fd (rfd_, -1, 0);
|
||||
close_resources ();
|
||||
}
|
||||
|
||||
void IoService::stop ()
|
||||
{
|
||||
stop_ = true;
|
||||
wakeup ();
|
||||
Thread::stop ();
|
||||
}
|
||||
|
||||
void IoService::handle_request (EventAction* act)
|
||||
{
|
||||
Event ev;
|
||||
|
||||
if (act)
|
||||
{
|
||||
switch (act->mode_)
|
||||
{
|
||||
case StreamModeConnect:
|
||||
if (connect_channel (act->fd_, (act->callback_ ? act->callback_->param () : ev)))
|
||||
schedule (act);
|
||||
else
|
||||
track (act);
|
||||
return;
|
||||
|
||||
case StreamModeAccept:
|
||||
track (act);
|
||||
return;
|
||||
|
||||
case StreamModeRead:
|
||||
if (read_channel (act->fd_, (act->callback_ ? act->callback_->param () : ev), 1))
|
||||
schedule (act);
|
||||
else
|
||||
track (act);
|
||||
return;
|
||||
|
||||
case StreamModeWrite:
|
||||
if (write_channel (act->fd_, (act->callback_ ? act->callback_->param () : ev)))
|
||||
schedule (act);
|
||||
else
|
||||
track (act);
|
||||
return;
|
||||
|
||||
case StreamModeEnd:
|
||||
if (close_channel (act->fd_, (act->callback_ ? act->callback_->param () : ev)))
|
||||
schedule (act);
|
||||
else
|
||||
track (act);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IoService::connect_channel (int fd, Event& ev)
|
||||
{
|
||||
struct sockaddr adr;
|
||||
int n = 0;
|
||||
|
||||
if (ev.buffer_.length () <= sizeof adr)
|
||||
ev.buffer_.copyout ((uint8_t*) &adr, (n = ev.buffer_.length ()));
|
||||
|
||||
int rv = ::connect (fd, &adr, n);
|
||||
switch (rv)
|
||||
{
|
||||
case 0:
|
||||
ev.type_ = Event::Done;
|
||||
break;
|
||||
case -1:
|
||||
switch (errno)
|
||||
{
|
||||
case EINPROGRESS:
|
||||
return false;
|
||||
default:
|
||||
ev.type_ = Event::Error;
|
||||
ev.error_ = errno;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IoService::read_channel (int fd, Event& ev, int flg)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = ::read (fd, read_pool_, sizeof read_pool_);
|
||||
if (len < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return false;
|
||||
default:
|
||||
ev.type_ = Event::Error;
|
||||
ev.error_ = errno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (len == 0)
|
||||
{
|
||||
ev.type_ = Event::EOS;
|
||||
}
|
||||
else if (flg & 1)
|
||||
{
|
||||
ev.type_ = Event::Done;
|
||||
ev.buffer_.append (read_pool_, len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IoService::write_channel (int fd, Event& ev)
|
||||
{
|
||||
struct iovec iov[IOV_MAX];
|
||||
size_t iovcnt;
|
||||
ssize_t len;
|
||||
|
||||
if (ev.buffer_.empty ())
|
||||
{
|
||||
ev.type_ = Event::Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
iovcnt = ev.buffer_.fill_iovec (iov, IOV_MAX);
|
||||
len = ::writev (fd, iov, iovcnt);
|
||||
if (len < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EAGAIN:
|
||||
return false;
|
||||
default:
|
||||
ev.type_ = Event::Error;
|
||||
ev.error_ = errno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((size_t) len < ev.buffer_.length ())
|
||||
{
|
||||
ev.buffer_.skip (len);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.type_ = Event::Done;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IoService::close_channel (int fd, Event& ev)
|
||||
{
|
||||
int rv = ::close (fd);
|
||||
if (rv == -1 && errno == EAGAIN)
|
||||
return false;
|
||||
|
||||
ev.type_ = Event::Done;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IoService::track (EventAction* act)
|
||||
{
|
||||
std::map<int, IoNode>::iterator it;
|
||||
int fd;
|
||||
|
||||
if (act)
|
||||
{
|
||||
fd = act->fd_;
|
||||
it = fd_map_.find (fd);
|
||||
|
||||
switch (act->mode_)
|
||||
{
|
||||
case StreamModeAccept:
|
||||
case StreamModeRead:
|
||||
if (it == fd_map_.end ())
|
||||
{
|
||||
IoNode node = {fd, true, false, act, 0};
|
||||
set_fd (fd, 1, 0, &(fd_map_[fd] = node));
|
||||
}
|
||||
else if (act->mode_ == StreamModeRead)
|
||||
{
|
||||
it->second.reading = true, it->second.read_action = act;
|
||||
set_fd (fd, 1, (it->second.writing ? 2 : 0), &it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (act->callback_) act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
}
|
||||
break;
|
||||
|
||||
case StreamModeConnect:
|
||||
case StreamModeWrite:
|
||||
case StreamModeEnd:
|
||||
if (it == fd_map_.end ())
|
||||
{
|
||||
IoNode node = {fd, false, true, 0, act};
|
||||
set_fd (fd, 0, 1, &(fd_map_[fd] = node));
|
||||
}
|
||||
else if (act->mode_ == StreamModeWrite)
|
||||
{
|
||||
it->second.writing = true, it->second.write_action = act;
|
||||
set_fd (fd, (it->second.reading ? 2 : 0), 1, &it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (act->callback_) act->callback_->param ().type_ = Event::Error;
|
||||
schedule (act);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IoService::cancel (EventAction* act)
|
||||
{
|
||||
std::map<int, IoNode>::iterator it;
|
||||
int fd;
|
||||
|
||||
if (act)
|
||||
{
|
||||
fd = act->fd_;
|
||||
it = fd_map_.find (fd);
|
||||
|
||||
switch (act->mode_)
|
||||
{
|
||||
case StreamModeAccept:
|
||||
case StreamModeRead:
|
||||
if (it != fd_map_.end () && it->second.read_action == act)
|
||||
{
|
||||
it->second.reading = false, it->second.read_action = 0;
|
||||
if (it->second.write_action == 0)
|
||||
fd_map_.erase (it);
|
||||
set_fd (fd, -1, (it->second.writing ? 2 : 0), &it->second);
|
||||
}
|
||||
break;
|
||||
|
||||
case StreamModeConnect:
|
||||
case StreamModeWrite:
|
||||
case StreamModeEnd:
|
||||
if (it != fd_map_.end () && it->second.write_action == act)
|
||||
{
|
||||
it->second.writing = false, it->second.write_action = 0;
|
||||
if (it->second.read_action == 0)
|
||||
fd_map_.erase (it);
|
||||
set_fd (fd, (it->second.reading ? 2 : 0), -1, &it->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
terminate (act);
|
||||
}
|
||||
}
|
||||
|
||||
void IoService::schedule (EventAction* act)
|
||||
{
|
||||
EventMessage msg = {1, act};
|
||||
event_system.take_message (msg);
|
||||
}
|
||||
|
||||
void IoService::terminate (EventAction* act)
|
||||
{
|
||||
EventMessage msg = {-1, act};
|
||||
event_system.take_message (msg);
|
||||
}
|
73
event/io_service.h
Normal file
73
event/io_service.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: io_service.h //
|
||||
// Description: servicing of network IO requests for the event system //
|
||||
// Project: WANProxy XTech //
|
||||
// Author: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EVENT_IO_SERVICE_H
|
||||
#define EVENT_IO_SERVICE_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <common/buffer.h>
|
||||
#include <common/ring_buffer.h>
|
||||
#include <common/thread/thread.h>
|
||||
#include <event/action.h>
|
||||
#include <event/event_callback.h>
|
||||
#include <event/event_message.h>
|
||||
|
||||
#define IO_READ_BUFFER_SIZE 0x10000
|
||||
#define IO_POLL_EVENT_COUNT 512
|
||||
|
||||
struct IoNode
|
||||
{
|
||||
int fd;
|
||||
bool reading;
|
||||
bool writing;
|
||||
EventAction* read_action;
|
||||
EventAction* write_action;
|
||||
};
|
||||
|
||||
class IoService : public Thread
|
||||
{
|
||||
private:
|
||||
LogHandle log_;
|
||||
RingBuffer<EventMessage> gateway_;
|
||||
uint8_t read_pool_[IO_READ_BUFFER_SIZE];
|
||||
std::map<int, IoNode> fd_map_;
|
||||
int handle_, rfd_, wfd_;
|
||||
|
||||
public:
|
||||
IoService ();
|
||||
virtual ~IoService ();
|
||||
|
||||
virtual void main ();
|
||||
virtual void stop ();
|
||||
|
||||
private:
|
||||
void handle_request (EventAction* act);
|
||||
bool connect_channel (int fd, Event& ev);
|
||||
bool read_channel (int fd, Event& ev, int flg);
|
||||
bool write_channel (int fd, Event& ev);
|
||||
bool close_channel (int fd, Event& ev);
|
||||
void track (EventAction* act);
|
||||
void cancel (EventAction* act);
|
||||
void schedule (EventAction* act);
|
||||
void terminate (EventAction* act);
|
||||
|
||||
void open_resources ();
|
||||
void close_resources ();
|
||||
void set_fd (int fd, int rd, int wr, IoNode* node = 0);
|
||||
void poll (int ms);
|
||||
|
||||
public:
|
||||
bool idle () const { return fd_map_.empty (); }
|
||||
void wakeup () { ::write (wfd_, "*", 1); }
|
||||
void take_message (const EventMessage& msg) { gateway_.write (msg); wakeup (); }
|
||||
};
|
||||
|
||||
#endif /* !EVENT_IO_SERVICE_H */
|
41
event/lib.mk
Normal file
41
event/lib.mk
Normal file
|
@ -0,0 +1,41 @@
|
|||
VPATH+= ${TOPDIR}/event
|
||||
|
||||
SRCS+= event_system.cc
|
||||
SRCS+= io_service.cc
|
||||
|
||||
ifndef USE_POLL
|
||||
ifeq "${OSNAME}" "Darwin"
|
||||
USE_POLL= kqueue
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "FreeBSD"
|
||||
USE_POLL= kqueue
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "OpenBSD"
|
||||
USE_POLL= kqueue
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "Linux"
|
||||
USE_POLL= epoll
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "Interix"
|
||||
USE_POLL= select
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "SunOS"
|
||||
USE_POLL= port
|
||||
endif
|
||||
|
||||
ifndef USE_POLL
|
||||
USE_POLL= poll
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "${OSNAME}" "Linux"
|
||||
# Required for clock_gettime(3).
|
||||
LDADD+= -lrt
|
||||
endif
|
||||
|
||||
SRCS+= event_poll_${USE_POLL}.cc
|
107
event/object_callback.h
Normal file
107
event/object_callback.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_OBJECT_CALLBACK_H
|
||||
#define EVENT_OBJECT_CALLBACK_H
|
||||
|
||||
#include <event/callback.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: object_callback.h //
|
||||
// Description: template classes for event callback handling //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class C>
|
||||
class ObjectMethodCallback : public Callback {
|
||||
public:
|
||||
typedef void (C::*const method_t)(void);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
public:
|
||||
template<typename T>
|
||||
ObjectMethodCallback(C *obj, T method)
|
||||
: Callback(),
|
||||
obj_(obj),
|
||||
method_(method)
|
||||
{ }
|
||||
|
||||
~ObjectMethodCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
(obj_->*method_)();
|
||||
}
|
||||
};
|
||||
|
||||
template<class C, typename A>
|
||||
class ObjectMethodArgCallback : public Callback {
|
||||
public:
|
||||
typedef void (C::*const method_t)(A);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
A arg_;
|
||||
public:
|
||||
template<typename Tm>
|
||||
ObjectMethodArgCallback(C *obj, Tm method, A arg)
|
||||
: Callback(),
|
||||
obj_(obj),
|
||||
method_(method),
|
||||
arg_(arg)
|
||||
{ }
|
||||
|
||||
~ObjectMethodArgCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
(obj_->*method_)(arg_);
|
||||
}
|
||||
};
|
||||
|
||||
template<class C>
|
||||
Callback *callback(C *obj, typename ObjectMethodCallback<C>::method_t method)
|
||||
{
|
||||
Callback *cb = new ObjectMethodCallback<C>(obj, method);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
template<class C, typename A>
|
||||
Callback *callback(C *obj, void (C::*const method)(A), A arg)
|
||||
{
|
||||
Callback *cb = new ObjectMethodArgCallback<C, A>(obj, method, arg);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
#endif /* !EVENT_OBJECT_CALLBACK_H */
|
138
event/typed_callback.h
Normal file
138
event/typed_callback.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_TYPED_CALLBACK_H
|
||||
#define EVENT_TYPED_CALLBACK_H
|
||||
|
||||
#include <event/callback.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: typed_callback.h //
|
||||
// Description: template classes for event callback handling //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
class TypedCallback : public Callback {
|
||||
protected:
|
||||
T param_;
|
||||
|
||||
protected:
|
||||
TypedCallback()
|
||||
: Callback(),
|
||||
param_()
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual ~TypedCallback()
|
||||
{ }
|
||||
|
||||
void param(T p)
|
||||
{
|
||||
param_ = p;
|
||||
}
|
||||
|
||||
T& param()
|
||||
{
|
||||
return param_;
|
||||
}
|
||||
|
||||
void reset(void)
|
||||
{
|
||||
param_ = T();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, class C>
|
||||
class ObjectTypedCallback : public TypedCallback<T> {
|
||||
public:
|
||||
typedef void (C::*const method_t)(T);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
public:
|
||||
template<typename Tm>
|
||||
ObjectTypedCallback(C *obj, Tm method)
|
||||
: TypedCallback<T>(),
|
||||
obj_(obj),
|
||||
method_(method)
|
||||
{ }
|
||||
|
||||
~ObjectTypedCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
(obj_->*method_)(TypedCallback<T>::param_);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, class C, typename A>
|
||||
class ObjectTypedArgCallback : public TypedCallback<T> {
|
||||
public:
|
||||
typedef void (C::*const method_t)(T, A);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
A arg_;
|
||||
public:
|
||||
template<typename Tm>
|
||||
ObjectTypedArgCallback(C *obj, Tm method, A arg)
|
||||
: TypedCallback<T>(),
|
||||
obj_(obj),
|
||||
method_(method),
|
||||
arg_(arg)
|
||||
{ }
|
||||
|
||||
~ObjectTypedArgCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
(obj_->*method_)(TypedCallback<T>::param_, arg_);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, class C>
|
||||
TypedCallback<T> *callback(C *obj, void (C::*const method)(T))
|
||||
{
|
||||
TypedCallback<T> *cb = new ObjectTypedCallback<T, C>(obj, method);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
template<typename T, class C, typename A>
|
||||
TypedCallback<T> *callback(C *obj, void (C::*const method)(T, A), A arg)
|
||||
{
|
||||
TypedCallback<T> *cb = new ObjectTypedArgCallback<T, C, A>(obj, method, arg);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
#endif /* !EVENT_TYPED_CALLBACK_H */
|
141
event/typed_pair_callback.h
Normal file
141
event/typed_pair_callback.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 Juli Mallett. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EVENT_TYPED_PAIR_CALLBACK_H
|
||||
#define EVENT_TYPED_PAIR_CALLBACK_H
|
||||
|
||||
#include <event/callback.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// File: typed_pair_callback.h //
|
||||
// Description: template classes for event callback handling //
|
||||
// Project: WANProxy XTech //
|
||||
// Adapted by: Andreu Vidal Bramfeld-Software //
|
||||
// Last modified: 2015-04-01 //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Feels like I can get std::pair and some sort
|
||||
* of application template to do the heavy lifting
|
||||
* here to avoid duplication of TypedCallback<T>.
|
||||
*/
|
||||
template<typename Ta, typename Tb>
|
||||
class TypedPairCallback : public Callback {
|
||||
protected:
|
||||
bool have_param_;
|
||||
std::pair<Ta, Tb> param_;
|
||||
|
||||
protected:
|
||||
TypedPairCallback()
|
||||
: Callback(),
|
||||
have_param_(false),
|
||||
param_()
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual ~TypedPairCallback()
|
||||
{ }
|
||||
|
||||
public:
|
||||
void param(Ta a, Tb b)
|
||||
{
|
||||
param_.first = a;
|
||||
param_.second = b;
|
||||
have_param_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ta, typename Tb, class C>
|
||||
class ObjectTypedPairCallback : public TypedPairCallback<Ta, Tb> {
|
||||
public:
|
||||
typedef void (C::*const method_t)(Ta, Tb);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
public:
|
||||
template<typename Tm>
|
||||
ObjectTypedPairCallback(C *obj, Tm method)
|
||||
: TypedPairCallback<Ta, Tb>(),
|
||||
obj_(obj),
|
||||
method_(method)
|
||||
{ }
|
||||
|
||||
~ObjectTypedPairCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
ASSERT("/typed/pair/callback", (TypedPairCallback<Ta,Tb>::have_param_));
|
||||
(obj_->*method_)((TypedPairCallback<Ta,Tb>::param_.first), (TypedPairCallback<Ta,Tb>::param_.second));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ta, typename Tb, class C, typename A>
|
||||
class ObjectTypedPairArgCallback : public TypedPairCallback<Ta, Tb> {
|
||||
public:
|
||||
typedef void (C::*const method_t)(Ta, Tb, A);
|
||||
|
||||
private:
|
||||
C *const obj_;
|
||||
method_t method_;
|
||||
A arg_;
|
||||
public:
|
||||
template<typename Tm>
|
||||
ObjectTypedPairArgCallback(C *obj, Tm method, A arg)
|
||||
: TypedPairCallback<Ta, Tb>(),
|
||||
obj_(obj),
|
||||
method_(method),
|
||||
arg_(arg)
|
||||
{ }
|
||||
|
||||
~ObjectTypedPairArgCallback()
|
||||
{ }
|
||||
|
||||
virtual void execute ()
|
||||
{
|
||||
ASSERT("/typed/pair/callback", (TypedPairCallback<Ta,Tb>::have_param_));
|
||||
(obj_->*method_)((TypedPairCallback<Ta,Tb>::param_.first), (TypedPairCallback<Ta,Tb>::param_.second), arg_);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ta, typename Tb, class C>
|
||||
TypedPairCallback<Ta, Tb> *callback(C *obj, void (C::*const method)(Ta, Tb))
|
||||
{
|
||||
TypedPairCallback<Ta, Tb> *cb = new ObjectTypedPairCallback<Ta, Tb, C>(obj, method);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
template<typename Ta, typename Tb, class C, typename A>
|
||||
TypedPairCallback<Ta, Tb> *callback(C *obj, void (C::*const method)(Ta, Tb, A), A arg)
|
||||
{
|
||||
TypedPairCallback<Ta, Tb> *cb = new ObjectTypedPairArgCallback<Ta, Tb, C, A>(obj, method, arg);
|
||||
return (cb);
|
||||
}
|
||||
|
||||
#endif /* !EVENT_TYPED_PAIR_CALLBACK_H */
|
Loading…
Add table
Add a link
Reference in a new issue