root/lang/objective-cplusplus/i3/trunk/src/mil/include/mil/ModuleCommon.h @ 36274

Revision 36274, 6.6 kB (checked in by saturday06, 4 years ago)

oioo

Line 
1#pragma once
2
3#include "Thread.h"
4#include "Memory.h"
5
6namespace mil {
7
8class Tls {
9    struct Data {
10#ifdef MIL_GUI_WINDOWS
11        HWND window_cache;
12#else
13        NSWindow* window_cache;
14#endif
15    } data[MIL_MAX_THREADS];
16    Data dummy;
17public:
18    Data& getData(thread::id_t thread_id) {
19        if (!thread::is_valid_id(thread_id)) {
20            // Error
21            return dummy;
22        }
23        return data[thread_id];
24    }
25    void flush() {
26        for (size_t i = 0; i < _countof(data); i++) {
27            data[i].window_cache = NULL;
28        }
29    }
30    const thread::id_t thread_id;
31    pool::Producer producer;
32    pool::Consumer consumer;
33    Tls(thread::id_t thread_id) : thread_id(thread_id), producer(thread_id) {
34        memset(&data, 0, sizeof(data));
35        memset(&dummy, 0, sizeof(dummy));
36    }
37};
38
39struct ExitEvent {
40    typedef SFINAE_CONDITION IsExitEvent;
41};
42
43struct ModuleExecuteProxy {
44    template <class EventData, class Target>
45    static void execute_body(EventData& data, Target& target, typename EventData::IsReturnMemoryEvent) {
46        target.tls.producer.free(data.memory);
47    }
48
49    template <class EventData, class Target>
50    static void execute_body(EventData&, Target& target, typename EventData::IsExitEvent) {
51        MIL_MODULE_SUPER_CHILD_TYPE(Target)& o =
52            MIL_MODULE_GET_SUPER_CHILD(target);
53        o.destroy();
54    }
55
56    template <class EventData, class Target>
57    static void execute_body(EventData& data, Target& target, ...) {
58        MIL_MODULE_SUPER_CHILD_TYPE(Target)& o =
59            MIL_MODULE_GET_SUPER_CHILD(target);
60       
61        o.execute_hook(data);
62        o.execute(data);
63    }
64
65//    template <class, class Target>
66//    static void execute_body(ExitEvent, Target& target, ...) {
67//        MIL_MODULE_SUPER_CHILD_TYPE(Target)& o =
68//            MIL_MODULE_GET_SUPER_CHILD(target);
69//        o.destroy();
70//    }
71
72    template <class EventData, class Target>
73    static void execute(EventData& data, Target& target) {
74        execute_body<EventData, Target>(data, target, SFINAE_DUMMY_VALUE);
75    }
76};
77
78template <class T>
79void post_exit_template(void* obj, void* event_memory) {
80    MIL_MODULE_SUPER_CHILD_TYPE(T)& o =
81        MIL_MODULE_GET_SUPER_CHILD(*reinterpret_cast<T*>(obj));
82
83    o.requestExit(event_memory);
84}
85
86template <class T>
87void join_template(void* obj) {
88    MIL_MODULE_SUPER_CHILD_TYPE(T)& o =
89        MIL_MODULE_GET_SUPER_CHILD(*reinterpret_cast<T*>(obj));
90
91    o.join();
92}
93
94struct AutoJoiner {
95    void* obj;
96    void (*post_exit)(void*, void*);
97    void (*join)(void*);
98    char event_memory[sizeof(void*) * 10];
99};
100
101void set_auto_join_body(AutoJoiner&);
102void do_auto_join();
103
104void set_tmalloc_post_body(void (*post)());
105
106template <class T>
107void set_auto_join(T* t) {
108    AutoJoiner a = {};
109    a.obj = reinterpret_cast<void*>(t);
110    a.post_exit = post_exit_template<T>;
111    a.join = join_template<T>;
112    set_auto_join_body(a);
113}
114
115template <class Event, class Target, class Sender>
116void dispatcher_free_event(Event& event, Target& target) {
117    if (is_exit_event<Event>()) {
118        return;
119    }
120
121    if (is_return_memory_event<Event>() || unlikely(event.owner_id == target.thread_id)) {
122        // ReturnMemoryEvent
123        size_t blocks = pool::bytes_to_blocks(return_memory_considered_sizeof<Event>());
124        target.tls.producer.free(&event, blocks);
125        return;
126    }
127
128    pool::MemoryList* m = target.tls.consumer.pop(event.owner_id);
129    if (!m) {
130        target.tls.consumer.store(&event);
131        return;
132    }
133
134    pool::ReturnMemoryEvent<sizeof(Event)> e;
135    e.memory = m;
136    void* sender = thread::get(event.owner_id);
137    if (unlikely(!sender)) {
138        return;
139    }
140    (reinterpret_cast<Sender*>(sender))->post(e, target, (void*)&event, event.owner_id);
141}
142
143typedef void (*post_tfree_memory_function)(void*, pool::MemoryList*, thread::id_t);
144extern post_tfree_memory_function posts[MIL_MAX_THREADS];
145
146template <class Child, template <class> class ThreadType = MIL_DEFAULT_THREAD>
147class ModuleCommon : public Thread<ModuleCommon<Child, ThreadType>, ThreadType> {
148public:
149    Tls tls;
150    MIL_CRTP_CLASS_MEMBERS;
151
152        template <class Event>
153        void execute_hook_(Event&) {}
154
155        template <class Event>
156    void execute_hook(Event&) // no bracket
157
158
159    ModuleCommon() : tls(this->thread_id) {
160        set_auto_join(&MIL_MODULE_GET_SUPER_CHILD(*this));
161        posts[this->thread_id] = &post_tfree_memory<Child>;
162    }
163
164    ~ModuleCommon() {
165    }
166
167protected:
168    struct TMemory {
169        void setMalloced() {
170            owner_id |= (1 << (sizeof(owner_id) * 8 - 1));
171        }
172        bool isMalloced() {
173                        return (owner_id & (1 << (sizeof(owner_id) * 8 - 1))) ? true : false;
174        }
175        mil::thread::id_t owner_id;
176    };
177    struct TMemoryStore {
178        union {
179            mil::thread::id_t owner_id;
180            char padding[pool::BLOCK_SIZE];
181        };
182    };
183
184    template <class Receiver>
185    static void post_tfree_memory(void* memory, pool::MemoryList* list, thread::id_t receiver_id)  {
186        pool::ReturnMemoryEvent<pool::BLOCK_SIZE> e;
187        e.memory = list;
188        Receiver& receiver = *(reinterpret_cast<Receiver*>(thread::get(receiver_id)));
189        receiver.post(e, receiver, memory, receiver_id);
190    }
191
192    void* tmalloc(size_t size) {
193        TMemory* tmemory = NULL;
194        if ((size + sizeof(TMemory)) <= mil::pool::BLOCK_SIZE) {
195            tmemory = (TMemory*)tls.producer.malloc<mil::pool::BLOCK_SIZE>();
196            tmemory->owner_id = this->thread_id;
197        } else {
198            tmemory = (TMemory*)malloc(size + sizeof(TMemory));
199            tmemory->setMalloced();
200        }
201        return (void*)(((TMemory*)tmemory) + 1);
202    }
203
204    void tfree(void* memory_) {
205        TMemory* tmemory = (((TMemory*)memory_) - 1);
206        if (tmemory->isMalloced()) {
207            free(tmemory);
208            return;
209        }
210
211        pool::MemoryList* m = this->tls.consumer.pop(tmemory->owner_id);
212        if (!m) {
213            this->tls.consumer.store((TMemoryStore*)tmemory);
214            return;
215        }
216
217        posts[tmemory->owner_id](tmemory, m, tmemory->owner_id);
218    }
219};
220
221class ExitNotifier : public ModuleCommon<ExitNotifier, MIL_DEFAULT_THREAD> {
222public:
223    void requestExit(void*) {
224    }
225
226    template <typename T, typename Sender>
227    void post(const T&, Sender&, void*, thread::id_t) {
228    }
229
230    template <typename T, typename Sender>
231    void post(const T& event, Sender& sender) {
232    }
233};
234extern ExitNotifier exitNotifier;
235
236}
237
Note: See TracBrowser for help on using the browser.