6a5d0b73f2be5dce647ead7411b4def996d931e1
[senf.git] / Scheduler / ReadHelper.ct
1 // $Id$
2 //
3 // Copyright (C) 2006 
4
5 // Definition of non-inline template functions
6
7 #include "ReadHelper.ih"
8
9 // Custom includes
10 #include <errno.h>
11 #include "Utils/membind.hh"
12 #include "Utils/Exception.hh"
13 #include "Scheduler.hh"
14
15 #define prefix_
16 ///////////////////////////////ct.p////////////////////////////////////////
17
18 template <class Handle>
19 prefix_ senf::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
20                                                     InternalPredicate * predicate, Callback cb)
21     : handle_(handle), maxSize_(maxSize), predicate_(predicate), callback_(cb), 
22       errno_(0), complete_(false)
23 {
24     // Here we add a *static* member taking a *smart* pointer as first
25     // argumnet instead of a simple bound-member as callback to the
26     // scheduler. This ensures, that the refcount is at least 1 as
27     // long as the helper is registered with the scheduler.
28     senf::Scheduler::instance()
29         .add(handle,boost::bind(&ReadHelper::dispatchProcess,ptr(this),_1,_2),
30              senf::Scheduler::EV_READ);
31 }
32
33 template <class Handle>
34 prefix_ void senf::ReadHelper<Handle>::revoke()
35 {
36     ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
37     senf::Scheduler::instance()
38         .remove(handle_,senf::Scheduler::EV_READ);
39 }
40
41 template <class Handle>
42 prefix_ void
43 senf::ReadHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
44                                                  senf::Scheduler::EventId event)
45 {
46     // since we have a 'ptr' argument, the instance cannot be deleted
47     // before this method returns
48     return helper->process(handle,event);
49 }
50
51 template <class Handle>
52 prefix_ void senf::ReadHelper<Handle>::process(Handle handle,
53                                                       senf::Scheduler::EventId event)
54 {
55     try {
56         if (event != senf::Scheduler::EV_READ)
57             throw SystemException(EPIPE);
58         std::string rcv (handle.read(maxSize_ - data_.size()));
59         data_.append(rcv);
60         std::string::size_type n = predicate_ ? (*predicate_)(data_) : std::string::npos;
61         if (n != std::string::npos || data_.size() >= maxSize_ || rcv.size() == 0) {
62             complete_ = true;
63             if (n < data_.size()) {
64                 tail_.assign(data_,n,std::string::npos);
65                 data_.erase(n);
66             }
67             done();
68         }
69     }
70     catch (senf::SystemException const & ex) {
71         errno_ = ex.err;
72         done();
73     }
74 }
75
76 template <class Handle>
77 prefix_ void senf::ReadHelper<Handle>::done()
78 {
79     revoke();
80     callback_(ptr(this));
81 }
82
83 template <class Handle>
84 template <class Predicate>
85 prefix_ std::string::size_type
86 senf::ReadHelper<Handle>::InternalPredicate::Dispatcher<Predicate>::
87 operator()(std::string const & data)
88 {
89     return predicate(data);
90 }
91
92 ///////////////////////////////ct.e////////////////////////////////////////
93 #undef prefix_
94
95 \f
96 // Local Variables:
97 // mode: c++
98 // End: