root/lang/c/mpio/trunk/mp/io.erb.h @ 6740

Revision 6740, 5.7 kB (checked in by frsyuki, 6 years ago)

lang/c/mpio: implemented dispatch::modify()

Line 
1#ifndef MP_IO_H__
2#define MP_IO_H__
3
4#include "mp/event.h"
5#include "mp/mempool.h"
6#include <cstring>
7#include <stdint.h>
8#include <errno.h>
9
10/*
11 * fd: 0000 0000 0000 0000 0000 0000 0000 0000
12 *     ^\________________/ ^\________________/
13 *     |       flags       |      flags
14 *     \------- or --------/ (depends on endian)
15 *                \ switch bit (1=no switch, 0=switch)
16 * event: switch bit is on => (short)event
17 *        continue flag    => not used
18 *        end flag         => (int)error
19 */
20
21#define MP_IO_SWITCH_FLAG -1
22#define MP_IO_NEXT_FD(next)    ((int)(next >> 32))
23#define MP_IO_NEXT_EVENT(next) ((short)(next & 0xffffffff))
24#define MP_IO_NEXT_ERORR(next) ((int)(next & 0xffffffff))
25#define MP_IO_CONTINUE_FLAG 0x1
26#define MP_IO_END_FLAG      0x2
27#define MP_IO_IS_SWITCH(fd)   (fd >= 0)
28#define MP_IO_IS_CONTINUE(fd) (fd & MP_IO_CONTINUE_FLAG)
29#define MP_IO_IS_END(fd)      (fd & MP_IO_END_FLAG)
30#define MP_IOS_SWITCH_EVENT(fd, event) (((uint64_t)fd) << 32 | event)
31#define MP_IOS_START(fd, event) MP_IOS_SWITCH_EVENT(fd, event)
32#define MP_IOS_CONTINUE   MP_IOS_SWITCH_EVENT(MP_IO_SWITCH_FLAG | MP_IO_CONTINUE_FLAG, 0)
33#define MP_IOS_END(error) MP_IOS_SWITCH_EVENT(MP_IO_SWITCH_FLAG | MP_IO_END_FLAG, error)
34
35#define MP_IOS_INITIALIZE(...) \
36template <typename Data> static next_t set(iocb<Data>& cb, __VA_ARGS__)
37
38#define MP_IOS_OPERATOR(...) \
39template <typename Data> static next_t run(iocb<Data>& cb, __VA_ARGS__)
40
41namespace mp {
42
43
44namespace ios {
45        typedef uint64_t next_t;
46        struct ios {
47                virtual ~ios() {}
48                virtual next_t operator() (int fd, short event) = 0;
49        };
50}
51
52
53template <typename Data>
54class io {
55public:
56        typedef Data data_t;
57        struct stdbuffer_t {
58                int i[2];
59                short s;
60                size_t sz[2];
61                union {
62                        void* p;
63                        size_t sz;
64                        uint64_t u64;
65                } m[4];
66                void* p[2];
67        };
68public:
69        io(data_t data_ = Data(), size_t initial_length = 8);
70        int run(void);
71        template <typename IOS>
72                int add(int fd, short event, IOS ios);
73        template <typename Callback, typename Argument, typename Finalize>
74                int add(int fd, short event, Callback* ios_callback, Argument ios_obj, Finalize* ios_finalize);
75public:
76        mempool<> pool;
77        data_t data;
78private:
79        enum {
80                IOS_ALLOCATE_STDBUFFER = 0,
81                IOS_ALLOCATE_POOL = 1,
82        };
83        struct event_data {
84                next_t (*ios_callback)(void*, int, short);
85                void (*ios_finalize)(void*);
86                void* ios_obj;
87                char databuf[sizeof(stdbuffer_t)];
88                short ios_allocation_type;
89                short event;
90        };
91        typedef event<event_data> event_t;
92        event_t m_event;
93private:
94        template <typename IOS>
95        static int object_callback(void* obj, int fd, short event);
96        template <typename IOS>
97        static int object_finalize(void* obj);
98private:
99        io(const io&);
100};
101
102
103template <typename Data>
104io<Data>::io(data_t data_, size_t initial_length) :
105                data(data_), m_event(initial_length) {}
106
107template <typename Data>
108template <typename IOS>
109int io<Data>::add(int fd, short event, IOS ios)
110{
111        int ret = m_event.add(fd, event, event_data());
112        event_data& ed( m_event.data(fd) );
113        ed.event = event;
114        ed.ios_callback = object_callback<IOS>;
115        ed.ios_finalize = object_finalize<IOS>;
116        if( sizeof(IOS) <= sizeof(stdbuffer_t) ) {
117                ed.ios_obj = new (ed.databuf) IOS(ios);
118                ed.ios_allocation_type = IOS_ALLOCATE_STDBUFFER;
119        } else {
120                ed.ios_obj = new (pool.malloc<sizeof(IOS)>()) IOS(ios);
121                ed.ios_allocation_type = IOS_ALLOCATE_POOL;
122        }
123        return ret;
124}
125
126template <typename Data>
127template <typename Callback, typename Argument, typename Finalize>
128int io<Data>::add(int fd, short event, Callback* ios_callback, Argument ios_obj, Finalize* ios_finalize)
129{
130        int ret = m_event.add(fd, event, event_data());
131        event_data& ed( m_event.data(fd) );
132        ed.event = event;
133        ed.ios_callback = ios_callback;
134        ed.ios_finalize = ios_finalize;
135        if( sizeof(Argument) <= sizeof(stdbuffer_t) ) {
136                ed.ios_obj = new (ed.databuf) Argument(ios_obj);
137                ed.ios_allocation_type = IOS_ALLOCATE_STDBUFFER;
138        } else {
139                ed.ios_obj = new (pool.malloc<sizeof(Argument)>()) Argument(ios_obj);
140                ed.ios_allocation_type = IOS_ALLOCATE_POOL;
141        }
142        return ret;
143}
144
145
146template <typename Data>
147template <typename IOS>
148int io<Data>::object_callback(void* obj, int fd, short event)
149{
150        return (*reinterpret_cast<IOS*>(obj))(fd, event);
151}
152
153template <typename IOS>
154static void object_finalize(void* obj)
155{
156        reinterpret_cast<IOS*>(obj)->~IOS();
157}
158
159
160template <typename Data>
161int io<Data>::run(void)
162{
163        event_data* ed;
164        int fd;
165        short event;
166        int ret;
167        while(1) {
168                while( m_event.next(&fd, &event, &ed) ) {
169                        ios::next_t next = (*ed->ios_callback)(ed->ios_obj, fd, event);
170                        int next_fd = MP_IO_NEXT_FD(next);
171                        if( MP_IO_IS_SWITCH(next_fd) ) {
172                                short next_event = MP_IO_NEXT_EVENT(next);
173                                if( (ret = m_event.remove(fd, event)) < 0 ) {
174                                        return ret;
175                                }
176                                ed->event = next_event;
177                                if( (ret = m_event.add(next_fd, next_event, *ed)) < 0 ) {
178                                        return ret;
179                                }
180                        } else if( MP_IO_IS_END(next_fd) ) {
181                                int error = MP_IO_NEXT_ERORR(next);
182                                (*ed->ios_finalize)(ed->ios_obj);
183                                if( ed->ios_allocation_type == IOS_ALLOCATE_STDBUFFER ) {
184                                        // do nothing
185                                } else {  // ed->ios_allocation_type == IOS_ALLOCATE_POOL )
186                                        pool.destroy(ios);
187                                }
188                                if( error < 0 ) {
189                                        return error;
190                                }
191                        } else {  // MP_IO_IS_CONTINUE(next_fd)
192                                // do nothing
193                        }
194                }
195                if( (ret = m_event.wait()) < 0 ) { return ret; }
196        }
197}
198
199
200namespace ios {
201        template <typename Sig, typename F>
202        struct ios_callback;
203<%
204def args(n, sep = "", &block)
205        Array.new(n) {|i| yield i+1 } .join(sep)
206end
207-%>
208<% (0..16).each do |n| -%>
209        template <typename F, typename R<%= args(n) {|i| ", typename A#{i}" } %>>
210        struct ios_callback<R (<%= args(n, ", ") {|i| "A#{i}" } %>), F> {
211                ios_callback(F f) : _f(f) {}
212                R operator()(<%= args(n, ", ") {|i| "A#{i} a#{i}" } %>)
213                { return _f(<%= args(n, ", ") {|i| "a#{i}" } %>); }
214        private: F _f;
215        };
216<% end -%>
217}
218
219
220}  // namespace mp
221
222#endif /* mp/io.h */
223
Note: See TracBrowser for help on using the browser.