--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Definition of inline non-template functions
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ satcom::lib::ReadUntil::ReadUntil(std::string target_)
+ : target(target_)
+{}
+
+prefix_ std::string::size_type satcom::lib::ReadUntil::operator()(std::string data)
+{
+ return data.find(target);
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Definition of non-inline template functions
+
+#include "ReadHelper.ih"
+
+// Custom includes
+#include <errno.h>
+#include "Utils/membind.hh"
+#include "Utils/Exception.hh"
+#include "Scheduler.hh"
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class Handle>
+prefix_ satcom::lib::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
+ InternalPredicate * predicate, Callback cb)
+ : handle_(handle), maxSize_(maxSize), predicate_(predicate), callback_(cb),
+ errno_(0), complete_(false)
+{
+ // Here we add a *static* member taking a *smart* pointer as first
+ // argumnet instead of a simple bound-member as callback to the
+ // scheduler. This ensures, that the refcount is at least 1 as
+ // long as the helper is registered with the scheduler.
+ satcom::lib::Scheduler::instance()
+ .add(handle,boost::bind(&ReadHelper::dispatchProcess,ptr(this),_1,_2),
+ satcom::lib::Scheduler::EV_READ);
+}
+
+template <class Handle>
+prefix_ void satcom::lib::ReadHelper<Handle>::revoke()
+{
+ ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
+ satcom::lib::Scheduler::instance()
+ .remove(handle_,satcom::lib::Scheduler::EV_READ);
+}
+
+template <class Handle>
+prefix_ void
+satcom::lib::ReadHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
+ satcom::lib::Scheduler::EventId event)
+{
+ // since we have a 'ptr' argument, the instance cannot be deleted
+ // before this method returns
+ return helper->process(handle,event);
+}
+
+template <class Handle>
+prefix_ void satcom::lib::ReadHelper<Handle>::process(Handle handle,
+ satcom::lib::Scheduler::EventId event)
+{
+ try {
+ if (event != satcom::lib::Scheduler::EV_READ)
+ throw SystemException(EPIPE);
+ std::string rcv (handle.read(maxSize_ - data_.size()));
+ data_.append(rcv);
+ std::string::size_type n = predicate_ ? (*predicate_)(data_) : std::string::npos;
+ if (n != std::string::npos || data_.size() >= maxSize_ || rcv.size() == 0) {
+ complete_ = true;
+ if (n < data_.size()) {
+ tail_.assign(data_,n,std::string::npos);
+ data_.erase(n);
+ }
+ done();
+ }
+ }
+ catch (satcom::lib::SystemException const & ex) {
+ errno_ = ex.err;
+ done();
+ }
+}
+
+template <class Handle>
+prefix_ void satcom::lib::ReadHelper<Handle>::done()
+{
+ revoke();
+ callback_(ptr(this));
+}
+
+template <class Handle>
+template <class Predicate>
+prefix_ std::string::size_type
+satcom::lib::ReadHelper<Handle>::InternalPredicate::Dispatcher<Predicate>::
+operator()(std::string const & data)
+{
+ return predicate(data);
+}
+
+///////////////////////////////ct.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Definition of inline template functions
+
+#include "ReadHelper.ih"
+
+// Custom includes
+#include "Utils/Exception.hh"
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class Handle>
+prefix_ typename satcom::lib::ReadHelper<Handle>::ptr
+satcom::lib::ReadHelper<Handle>::dispatch(Handle handle, std::string::size_type maxSize,
+ Callback callback)
+{
+ return ptr(new ReadHelper(handle, maxSize, 0, callback));
+}
+
+template <class Handle>
+template <class Predicate>
+prefix_ typename satcom::lib::ReadHelper<Handle>::ptr
+satcom::lib::ReadHelper<Handle>::dispatch(Handle handle, std::string::size_type maxSize,
+ Predicate predicate, Callback callback)
+{
+ return ptr(new ReadHelper(handle, maxSize,
+ new typename InternalPredicate::template Dispatcher<Predicate>(predicate),
+ callback));
+}
+
+template <class Handle>
+prefix_ Handle satcom::lib::ReadHelper<Handle>::handle()
+ const
+{
+ return handle_;
+}
+
+template <class Handle>
+prefix_ unsigned satcom::lib::ReadHelper<Handle>::maxSize()
+ const
+{
+ return maxSize_;
+}
+
+template <class Handle>
+prefix_ std::string const & satcom::lib::ReadHelper<Handle>::data()
+ const
+{
+ return data_;
+}
+
+template <class Handle>
+prefix_ std::string const & satcom::lib::ReadHelper<Handle>::tail()
+ const
+{
+ return tail_;
+}
+
+template <class Handle>
+prefix_ bool satcom::lib::ReadHelper<Handle>::complete()
+ const
+{
+ return complete_;
+}
+
+template <class Handle>
+prefix_ bool satcom::lib::ReadHelper<Handle>::error()
+ const
+{
+ return errno_ != 0;
+}
+
+template <class Handle>
+prefix_ void satcom::lib::ReadHelper<Handle>::throw_error()
+ const
+{
+ if (errno_ != 0) throw SystemException(errno_);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// TODO: Move all not Handle dependent members to a ReadHandleBase class
+
+#ifndef HH_ReadHelper_
+#define HH_ReadHelper_ 1
+
+// Custom includes
+#include <string>
+#include <boost/function.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include "Utils/intrusive_refcount.hh"
+#include "Scheduler.hh"
+
+//#include "ReadHelper.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace satcom {
+namespace lib {
+
+ template <class Handle>
+ class ReadHelper
+ : public satcom::lib::intrusive_refcount
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::intrusive_ptr<ReadHelper> ptr;
+ typedef boost::function<void (ptr)> Callback;
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ static ptr dispatch(Handle handle, std::string::size_type maxSize,
+ Callback callback);
+
+ template <class Predicate>
+ static ptr dispatch(Handle handle, std::string::size_type maxSize, Predicate predicate,
+ Callback callback);
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ Handle handle() const;
+ unsigned maxSize() const;
+
+ std::string const & data() const;
+ std::string const & tail() const;
+
+ bool complete() const;
+ bool error() const;
+ void throw_error() const;
+
+ void revoke();
+
+ protected:
+
+ private:
+ struct InternalPredicate;
+
+ ReadHelper(Handle handle, unsigned maxSize, InternalPredicate * predicate, Callback cb);
+
+ static void dispatchProcess(ptr helper, Handle handle, satcom::lib::Scheduler::EventId event);
+ void process(Handle handle, satcom::lib::Scheduler::EventId event);
+ void done();
+
+ Handle handle_;
+ std::string::size_type maxSize_;
+ boost::scoped_ptr<InternalPredicate> predicate_;
+ Callback callback_;
+
+ std::string data_;
+ std::string tail_;
+ int errno_;
+ bool complete_;
+ };
+
+ struct ReadUntil
+ {
+ ReadUntil(std::string target);
+ std::string::size_type operator()(std::string data);
+ std::string target;
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "ReadHelper.cci"
+#include "ReadHelper.ct"
+#include "ReadHelper.cti"
+//#include "ReadHelper.mpp"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+#ifndef IH_ReadHelper_
+#define IH_ReadHelper_ 1
+
+// Custom includes
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace satcom {
+namespace lib {
+
+ template <class Handle>
+ struct ReadHelper<Handle>::InternalPredicate
+ {
+ virtual ~InternalPredicate() {}
+ template <class Predicate>
+ struct Dispatcher
+ : public ReadHelper<Handle>::InternalPredicate
+ {
+ Dispatcher(Predicate p) : predicate(p) {}
+ virtual std::string::size_type operator()(std::string const & data);
+ Predicate predicate;
+ };
+
+ virtual std::string::size_type operator()(std::string const & data) = 0;
+ };
+
+}}
+
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Unit tests
+
+//#include "ReadHelper.test.hh"
+//#include "ReadHelper.test.ih"
+
+// Custom includes
+#include "ReadHelper.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
SatSCons.Lib(env,
library = 'Scheduler',
sources = SatSCons.GlobSources(),
- LIBS = [ 'Utils' ])
+ LIBS = [ 'Socket', 'Utils' ])
throw SystemException(errno);
}
-prefix_ void satcom::lib::Scheduler::do_add(int fd, SimpleCallback const & cb, EventId eventMask)
+prefix_ void satcom::lib::Scheduler::do_add(int fd, SimpleCallback const & cb, int eventMask)
{
FdTable::iterator i (fdTable_.find(fd));
int action (EPOLL_CTL_MOD);
throw SystemException(errno);
}
-prefix_ void satcom::lib::Scheduler::do_remove(int fd, EventId eventMask)
+prefix_ void satcom::lib::Scheduler::do_remove(int fd, int eventMask)
{
FdTable::iterator i (fdTable_.find(fd));
if (i == fdTable_.end())
memset(&ev,0,sizeof(ev));
ev.events = i->second.epollMask();
ev.data.fd = fd;
-
+
int action (EPOLL_CTL_MOD);
if (ev.events==0) {
action = EPOLL_CTL_DEL;
{
terminate_ = false;
while (! terminate_) {
- struct epoll_event ev;
+
MicroTime timeNow = now();
while ( ! timerQueue_.empty() && timerQueue_.top().timeout <= timeNow ) {
timerQueue_.top().cb();
return;
int timeout = timerQueue_.empty() ? -1 : int((timerQueue_.top().timeout - timeNow)/1000);
+ struct epoll_event ev;
int events = epoll_wait(epollFd_, &ev, 1, timeout);
if (events<0)
// Hmm ... man epoll says, it will NOT return with EINTR ??
}
else if (ev.events & EPOLLHUP) {
- BOOST_ASSERT(spec.cb_hup);
- spec.cb_hup(EV_HUP);
+ if (spec.cb_hup)
+ spec.cb_hup(EV_HUP);
+ else if (ev.events & EPOLLERR) {
+ if (spec.cb_write) spec.cb_write(EV_HUP);
+ if (spec.cb_read) spec.cb_read(EV_HUP);
+ }
}
- else if (ev.events & EPOLLERR) {
- BOOST_ASSERT(spec.cb_err);
- spec.cb_err(EV_ERR);
+ else if (ev.events & EPOLLERR && ! ev.events & EPOLLHUP) {
+ if (spec.cb_err)
+ spec.cb_err(EV_ERR);
+ else {
+ if (spec.cb_write) spec.cb_write(EV_ERR);
+ if (spec.cb_read) spec.cb_read(EV_ERR);
+ }
}
+
}
}
template <class Handle>
prefix_ void satcom::lib::Scheduler::add(Handle const & handle,
typename GenericCallback<Handle>::Callback const & cb,
- EventId eventMask)
+ int eventMask)
{
// retrieve_filehandle is found via ADL
- do_add(retrieve_filehandle(handle),boost::bind(cb,handle,_1),eventMask);
+ SimpleCallback scb (boost::bind(cb,handle,_1));
+ int fd = retrieve_filehandle(handle);
+ do_add(fd,scb,eventMask);
}
template <class Handle>
-prefix_ void satcom::lib::Scheduler::remove(Handle const & handle, EventId eventMask)
+prefix_ void satcom::lib::Scheduler::remove(Handle const & handle, int eventMask)
{
// retrieve_filehandle is found via ADL
do_remove(retrieve_filehandle(handle),eventMask);
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+// TODO: Fix EventId parameter (probably to int) to allow |-ing without casting ...
+
#ifndef HH_Scheduler_
#define HH_Scheduler_ 1
template <class Handle>
void add(Handle const & handle,
typename GenericCallback<Handle>::Callback const & cb,
- EventId eventMask = EV_ALL);
+ int eventMask = EV_ALL);
template <class Handle>
- void remove(Handle const & handle, EventId eventMask = EV_ALL);
+ void remove(Handle const & handle, int eventMask = EV_ALL);
void timeout(unsigned long timeout, TimerCallback const & cb);
private:
Scheduler();
- void do_add(int fd, SimpleCallback const & cb, EventId eventMask = EV_ALL);
- void do_remove(int fd, EventId eventMask = EV_ALL);
+ void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
+ void do_remove(int fd, int eventMask = EV_ALL);
struct EventSpec
{
bool is_close(MicroTime a, MicroTime b)
{
- return (a<b ? b-a : a-b) < 1100;
+ return (a<b ? b-a : a-b) < 10100; // a little bit over 10ms
}
}
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Definition of non-inline template functions
+
+//#include "WriteHelper.ih"
+
+// Custom includes
+#include <errno.h>
+#include "Utils/Exception.hh"
+#include "Scheduler.hh"
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class Handle>
+prefix_ satcom::lib::WriteHelper<Handle>::WriteHelper(Handle handle, std::string data,
+ Callback callback)
+ : handle_(handle), data_(data), callback_(callback),
+ offset_(0), errno_(0)
+{
+ satcom::lib::Scheduler::instance()
+ .add(handle_, boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
+ satcom::lib::Scheduler::EV_WRITE);
+}
+
+template <class Handle>
+prefix_ std::string const & satcom::lib::WriteHelper<Handle>::data()
+ const
+{
+ if (offset_ > 0) {
+ data_.erase(0,offset_);
+ offset_ = 0;
+ }
+ return data_;
+}
+
+template <class Handle>
+prefix_ void satcom::lib::WriteHelper<Handle>::revoke()
+{
+ ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
+ satcom::lib::Scheduler::instance()
+ .remove(handle_, satcom::lib::Scheduler::EV_WRITE);
+}
+
+template <class Handle>
+prefix_ void
+satcom::lib::WriteHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
+ satcom::lib::Scheduler::EventId event)
+{
+ // since we have a 'ptr' argument, the instance cannot be deleted
+ // before this method returns
+ return helper->process(handle,event);
+}
+
+template <class Handle>
+prefix_ void satcom::lib::WriteHelper<Handle>::process(Handle handle,
+ satcom::lib::Scheduler::EventId event)
+{
+ try {
+ if (event != satcom::lib::Scheduler::EV_WRITE)
+ throw satcom::lib::SystemException(EPIPE);
+ offset_ += handle.write(data_.data()+offset_,data_.size()-offset_);
+ if (offset_ >= data_.size()) {
+ data_.erase();
+ done();
+ }
+ }
+ catch (satcom::lib::SystemException const & ex) {
+ errno_ = ex.err;
+ done();
+ }
+}
+
+template <class Handle>
+prefix_ void satcom::lib::WriteHelper<Handle>::done()
+{
+ revoke();
+ callback_(ptr(this));
+}
+
+///////////////////////////////ct.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Definition of inline template functions
+
+//#include "WriteHelper.ih"
+
+// Custom includes
+#include "Utils/Exception.hh"
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class Handle>
+prefix_ typename satcom::lib::WriteHelper<Handle>::ptr
+satcom::lib::WriteHelper<Handle>::dispatch(Handle handle, std::string data, Callback callback)
+{
+ return ptr(new WriteHelper(handle, data, callback));
+}
+
+template <class Handle>
+prefix_ Handle satcom::lib::WriteHelper<Handle>::handle()
+ const
+{
+ return handle_;
+}
+
+template <class Handle>
+prefix_ bool satcom::lib::WriteHelper<Handle>::complete()
+ const
+{
+ return data_.empty();
+}
+
+template <class Handle>
+prefix_ bool satcom::lib::WriteHelper<Handle>::error()
+ const
+{
+ return errno_ != 0;
+}
+
+template <class Handle>
+prefix_ void satcom::lib::WriteHelper<Handle>::throw_error()
+ const
+{
+ if (errno_ != 0)
+ throw satcom::lib::SystemException(errno_);
+}
+
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+#ifndef HH_WriteHelper_
+#define HH_WriteHelper_ 1
+
+// Custom includes
+#include <string>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/function.hpp>
+#include "Utils/intrusive_refcount.hh"
+#include "Scheduler.hh"
+
+//#include "WriteHelper.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace satcom {
+namespace lib {
+
+ template <class Handle>
+ class WriteHelper
+ : public satcom::lib::intrusive_refcount
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::intrusive_ptr<WriteHelper> ptr;
+ typedef boost::function<void (ptr)> Callback;
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ static ptr dispatch(Handle handle, std::string data, Callback callback);
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ Handle handle() const;
+
+ std::string const & data() const;
+
+ bool complete() const;
+ bool error() const;
+ void throw_error() const;
+
+ void revoke();
+
+ protected:
+
+ private:
+ WriteHelper(Handle handle, std::string data, Callback callback);
+
+ static void dispatchProcess(ptr helper, Handle handle, satcom::lib::Scheduler::EventId event);
+ void process(Handle handle, satcom::lib::Scheduler::EventId event);
+ void done();
+
+ Handle handle_;
+ mutable std::string data_;
+ Callback callback_;
+
+ mutable std::string::size_type offset_;
+ int errno_;
+ };
+
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "WriteHelper.cci"
+#include "WriteHelper.ct"
+#include "WriteHelper.cti"
+//#include "WriteHelper.mpp"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2006
+
+// Unit tests
+
+//#include "WriteHelper.test.hh"
+//#include "WriteHelper.test.ih"
+
+// Custom includes
+#include "WriteHelper.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// End: