Implement Read/WriteHelper
g0dil [Fri, 10 Nov 2006 23:10:53 +0000 (23:10 +0000)]
fix EPOLLERR and EPOLLHUP handling

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@152 270642c3-0616-0410-b53a-bc976706d245

15 files changed:
Scheduler/ReadHelper.cci [new file with mode: 0644]
Scheduler/ReadHelper.ct [new file with mode: 0644]
Scheduler/ReadHelper.cti [new file with mode: 0644]
Scheduler/ReadHelper.hh [new file with mode: 0644]
Scheduler/ReadHelper.ih [new file with mode: 0644]
Scheduler/ReadHelper.test.cc [new file with mode: 0644]
Scheduler/SConscript
Scheduler/Scheduler.cc
Scheduler/Scheduler.cti
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
Scheduler/WriteHelper.ct [new file with mode: 0644]
Scheduler/WriteHelper.cti [new file with mode: 0644]
Scheduler/WriteHelper.hh [new file with mode: 0644]
Scheduler/WriteHelper.test.cc [new file with mode: 0644]

diff --git a/Scheduler/ReadHelper.cci b/Scheduler/ReadHelper.cci
new file mode 100644 (file)
index 0000000..81d7e6a
--- /dev/null
@@ -0,0 +1,27 @@
+// $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:
diff --git a/Scheduler/ReadHelper.ct b/Scheduler/ReadHelper.ct
new file mode 100644 (file)
index 0000000..16d2850
--- /dev/null
@@ -0,0 +1,98 @@
+// $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:
diff --git a/Scheduler/ReadHelper.cti b/Scheduler/ReadHelper.cti
new file mode 100644 (file)
index 0000000..75613d2
--- /dev/null
@@ -0,0 +1,89 @@
+// $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:
diff --git a/Scheduler/ReadHelper.hh b/Scheduler/ReadHelper.hh
new file mode 100644 (file)
index 0000000..8f38b16
--- /dev/null
@@ -0,0 +1,103 @@
+// $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:
diff --git a/Scheduler/ReadHelper.ih b/Scheduler/ReadHelper.ih
new file mode 100644 (file)
index 0000000..e174b5f
--- /dev/null
@@ -0,0 +1,40 @@
+// $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:
diff --git a/Scheduler/ReadHelper.test.cc b/Scheduler/ReadHelper.test.cc
new file mode 100644 (file)
index 0000000..14a3686
--- /dev/null
@@ -0,0 +1,27 @@
+// $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:
index fc9284e..2909ad3 100644 (file)
@@ -7,4 +7,4 @@ SatSCons.StandardTargets(env)
 SatSCons.Lib(env,
              library = 'Scheduler',
              sources = SatSCons.GlobSources(),
-             LIBS = [ 'Utils' ])
+             LIBS = [ 'Socket', 'Utils' ])
index 4f39c4b..75ed7f8 100644 (file)
@@ -96,7 +96,7 @@ prefix_ satcom::lib::Scheduler::Scheduler()
         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);
@@ -120,7 +120,7 @@ prefix_ void satcom::lib::Scheduler::do_add(int fd, SimpleCallback const & cb, E
         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()) 
@@ -136,7 +136,7 @@ prefix_ void satcom::lib::Scheduler::do_remove(int fd, EventId eventMask)
     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;
@@ -164,7 +164,7 @@ prefix_ void satcom::lib::Scheduler::process()
 {
     terminate_ = false;
     while (! terminate_) {
-        struct epoll_event ev;
+
        MicroTime timeNow = now();
        while ( ! timerQueue_.empty() && timerQueue_.top().timeout <= timeNow ) {
            timerQueue_.top().cb();
@@ -174,6 +174,7 @@ prefix_ void satcom::lib::Scheduler::process()
            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 ??
@@ -200,13 +201,22 @@ prefix_ void satcom::lib::Scheduler::process()
         }
 
         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);
+           }
         }
+
     }
 }
 
index be41961..0bd2d7f 100644 (file)
 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);
index a535fad..6788f61 100644 (file)
@@ -20,6 +20,8 @@
 // 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
 
@@ -83,9 +85,9 @@ namespace lib {
         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);
 
@@ -97,8 +99,8 @@ namespace lib {
     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 
         {
index 26dd7fd..6845277 100644 (file)
@@ -190,7 +190,7 @@ namespace {
 
     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
     }
            
 }
diff --git a/Scheduler/WriteHelper.ct b/Scheduler/WriteHelper.ct
new file mode 100644 (file)
index 0000000..8ef626d
--- /dev/null
@@ -0,0 +1,89 @@
+// $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:
diff --git a/Scheduler/WriteHelper.cti b/Scheduler/WriteHelper.cti
new file mode 100644 (file)
index 0000000..e73fd19
--- /dev/null
@@ -0,0 +1,58 @@
+// $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:
diff --git a/Scheduler/WriteHelper.hh b/Scheduler/WriteHelper.hh
new file mode 100644 (file)
index 0000000..02c3161
--- /dev/null
@@ -0,0 +1,81 @@
+// $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:
diff --git a/Scheduler/WriteHelper.test.cc b/Scheduler/WriteHelper.test.cc
new file mode 100644 (file)
index 0000000..7cb91df
--- /dev/null
@@ -0,0 +1,27 @@
+// $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: