root/lang/objective-cplusplus/i3/trunk/src/mil/include/mil/Module.h @ 35592

Revision 35592, 4.4 kB (checked in by saturday06, 4 years ago)

もうだmぽ

Line 
1#pragma once
2#include "Mil.h"
3#include "Thread.h"
4#include "ModuleCommon.h"
5
6namespace mil {
7
8/**
9 * public members should be thread safe
10 */
11template <typename Child>
12class Module : public ModuleCommon<Module<Child> > {
13public:
14    Tls tls;
15    MIL_CRTP_CLASS_MEMBERS;
16
17private:
18    class EventBase : public boost::noncopyable {
19    public:
20        void (*execute)(void* event, void* target);
21        thread::id_t owner_id;
22        EventBase* next;
23    };
24
25    class EventList : public boost::noncopyable {
26        EventBase* head;
27        EventBase* tail;
28        Mutex mutex;
29    public:
30        EventList() {
31            head = NULL;
32            tail = NULL;
33        }
34
35        bool push(EventBase& e) {
36            synchronized (mutex) {
37                e.next = NULL;
38                if (head == NULL) { // tail == NULL
39                    head = &e;
40                    tail = &e;
41                    return true;
42                }
43                tail->next = &e;
44                tail = &e;
45            }
46            return false;
47        }
48
49        EventBase* pop() {
50            EventBase* result = NULL;
51            synchronized (mutex) {
52                if (!head) {
53                    return NULL;
54                }
55                result = head;
56                head = head->next;
57            }
58            return result;
59        }
60
61        //EventBase* top() {
62        //    synchronized (mutex) {
63        //        return head;
64        //    }
65
66        //    return NULL;
67        //}
68
69        void clear() {
70            synchronized (mutex) {
71                head = NULL;
72                tail = NULL;
73            }
74        }
75    };
76protected:
77    template <typename T>
78    class Event : public EventBase {
79    public:
80        typedef T DataType;
81        T data;
82    };
83
84    friend class Module_test;
85
86private:
87    EventList list;
88    Semaphore semaphore;
89    bool repost;
90    bool breakLoopRequest;
91
92public:
93    Module() : tls(this->thread_id), repost(false), breakLoopRequest(false) {
94    }
95
96    void run() {
97        MIL_MODULE_GET_SUPER_CHILD(*this).loop();
98    }
99
100protected:
101    void repostEvent() {
102        repost = true;
103    }
104
105    template <typename Data, typename Sender>
106    static void dispatcher(void* event_, void* target_) {
107        typedef Child Target;
108
109        // XXX type safety??
110        Target& target = *static_cast<Target*>(target_);
111        Event<Data>& event = *static_cast<Event<Data>*>(event_);
112        //target.list.pop();
113        target.repost = false;
114        ModuleExecuteProxy::execute<Data, Target>(event.data, target);
115        if (target.repost) {
116            target.list.push(event);
117            return;
118        }
119       
120        dispatcher_free_event(event, target);
121    }
122
123public:
124    template <typename T, typename Sender>
125    //void post(const T& event, Sender& sender, void* memory, intptr_t owner_id)
126    void post(const T& event, Sender&, void* memory, intptr_t owner_id) {
127        Event<T>* e = new(memory) Event<T>;
128        e->data = event;
129        e->execute = dispatcher<T, Sender>;
130        e->owner_id = owner_id;
131
132        if (list.push(*e)) {
133            semaphore.passeren();
134        }
135    }
136
137    template <typename T, typename Sender>
138    void post(const T& event, Sender& sender) {
139        pool::Producer& producer = sender.tls.producer;
140        void* memory = producer.malloc<sizeof(Event<T>)>();
141        if (unlikely(memory == NULL)) {
142            halt << "can't allocate event memory";
143            return;
144        }
145
146        post(event, sender, memory, sender.tls.thread_id);
147    }
148public:
149    void destroy() {
150        breakLoopRequest = true;
151    }
152
153    void requestExit(void* event_memory) {
154        list.clear();
155        exitNotifier.tls.flush();
156        ExitEvent e;
157        post(e, exitNotifier, event_memory, exitNotifier.tls.thread_id);
158    }
159
160    ~Module() {
161        do_auto_join();
162    }
163
164    bool execute_front() {
165        EventBase* e = list.pop();
166        if (!e) {
167            return false;
168        }
169        e->execute((void*)e, (void*)this);
170        return true;
171    }
172
173protected:
174    void loop() {
175        if (breakLoopRequest) {
176            halt << "loop() re-called";
177        }
178        while (!breakLoopRequest) {
179            if (!execute_front()) {
180                semaphore.verhoog();
181            }
182        }
183    }
184};
185
186}
Note: See TracBrowser for help on using the browser.