]>
Commit | Line | Data |
---|---|---|
86c152f2 BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
5b0ddd18 | 3 | Copyright (C) 2002 - 2009 PowerDNS.COM BV |
86c152f2 BH |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
22dc646a BH |
6 | it under the terms of the GNU General Public License version 2 |
7 | as published by the Free Software Foundation | |
f782fe38 MH |
8 | |
9 | Additionally, the license of this program contains a special | |
10 | exception which allows to distribute the program in binary form when | |
11 | it is linked against OpenSSL. | |
86c152f2 BH |
12 | |
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
06bd9ccf | 20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
86c152f2 BH |
21 | */ |
22 | #ifndef MTASKER_HH | |
23 | #define MTASKER_HH | |
15a0aaef | 24 | #include <stdint.h> |
86c152f2 BH |
25 | #include <signal.h> |
26 | #include <ucontext.h> | |
e377f866 JJS |
27 | // don't pollute the namespace with the DS register (i386 only) |
28 | #undef DS | |
86c152f2 | 29 | #include <queue> |
76473b92 | 30 | #include <vector> |
86c152f2 BH |
31 | #include <map> |
32 | #include <time.h> | |
27af6ab1 BH |
33 | #include <boost/multi_index_container.hpp> |
34 | #include <boost/multi_index/ordered_index.hpp> | |
35 | #include <boost/multi_index/key_extractors.hpp> | |
61b26744 | 36 | #include "namespaces.hh" |
b80f25df | 37 | #include "misc.hh" |
27af6ab1 | 38 | using namespace ::boost::multi_index; |
86c152f2 | 39 | |
b80f25df | 40 | // #define MTASKERTIMING 1 |
41 | ||
b786789d BH |
42 | struct KeyTag {}; |
43 | ||
86c152f2 BH |
44 | //! The main MTasker class |
45 | /** The main MTasker class. See the main page for more information. | |
16276aa8 RK |
46 | \tparam EventKey Type of the key with which events are to be identified. Defaults to int. |
47 | \tparam EventVal Type of the content or value of an event. Defaults to int. Cannot be set to void. | |
86c152f2 BH |
48 | \note The EventKey needs to have an operator< defined because it is used as the key of an associative array |
49 | */ | |
50 | template<class EventKey=int, class EventVal=int> class MTasker | |
51 | { | |
52 | private: | |
53 | ucontext_t d_kernel; | |
54 | std::queue<int> d_runQueue; | |
55 | std::queue<int> d_zombiesQueue; | |
56 | ||
ec6eacbc BH |
57 | struct ThreadInfo |
58 | { | |
59 | ucontext_t* context; | |
60 | char* startOfStack; | |
61 | char* highestStackSeen; | |
b80f25df | 62 | #ifdef MTASKERTIMING |
63 | CPUTime dt; | |
64 | unsigned int totTime; | |
65 | #endif | |
ec6eacbc | 66 | }; |
35ce8576 | 67 | |
ec6eacbc | 68 | typedef std::map<int, ThreadInfo> mthreads_t; |
35ce8576 BH |
69 | mthreads_t d_threads; |
70 | int d_tid; | |
71 | int d_maxtid; | |
72 | size_t d_stacksize; | |
73 | ||
74 | EventVal d_waitval; | |
7f1fa77d | 75 | enum waitstatusenum {Error=-1,TimeOut=0,Answer} d_waitstatus; |
35ce8576 BH |
76 | |
77 | public: | |
86c152f2 BH |
78 | struct Waiter |
79 | { | |
27af6ab1 | 80 | EventKey key; |
86c152f2 | 81 | ucontext_t *context; |
5b0ddd18 | 82 | struct timeval ttd; |
ec6eacbc | 83 | int tid; |
86c152f2 BH |
84 | }; |
85 | ||
27af6ab1 BH |
86 | typedef multi_index_container< |
87 | Waiter, | |
88 | indexed_by < | |
89 | ordered_unique<member<Waiter,EventKey,&Waiter::key> >, | |
5b0ddd18 | 90 | ordered_non_unique<tag<KeyTag>, member<Waiter,struct timeval,&Waiter::ttd> > |
27af6ab1 BH |
91 | > |
92 | > waiters_t; | |
93 | ||
86c152f2 | 94 | waiters_t d_waiters; |
27af6ab1 | 95 | |
86c152f2 BH |
96 | //! Constructor |
97 | /** Constructor with a small default stacksize. If any of your threads exceeds this stack, your application will crash. | |
98 | This limit applies solely to the stack, the heap is not limited in any way. If threads need to allocate a lot of data, | |
99 | the use of new/delete is suggested. | |
100 | */ | |
101 | MTasker(size_t stacksize=8192) : d_stacksize(stacksize) | |
102 | { | |
103 | d_maxtid=0; | |
104 | } | |
105 | ||
106 | typedef void tfunc_t(void *); //!< type of the pointer that starts a thread | |
5b0ddd18 | 107 | int waitEvent(EventKey &key, EventVal *val=0, unsigned int timeoutMsec=0, struct timeval* now=0); |
86c152f2 BH |
108 | void yield(); |
109 | int sendEvent(const EventKey& key, const EventVal* val=0); | |
110 | void getEvents(std::vector<EventKey>& events); | |
d23a4bc7 | 111 | void makeThread(tfunc_t *start, void* val); |
5b0ddd18 | 112 | bool schedule(struct timeval* now=0); |
86c152f2 | 113 | bool noProcesses(); |
e5d684f9 | 114 | unsigned int numProcesses(); |
c836dc19 | 115 | int getTid(); |
ec6eacbc | 116 | unsigned int getMaxStackUsage(); |
b80f25df | 117 | unsigned int getUsec(); |
9170fbaf | 118 | |
86c152f2 | 119 | private: |
782be36c | 120 | static void threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2); |
35ce8576 | 121 | EventKey d_eventkey; // for waitEvent, contains exact key it was awoken for |
86c152f2 BH |
122 | }; |
123 | #include "mtasker.cc" | |
caa6eefa | 124 | |
caa6eefa BH |
125 | #endif // MTASKER_HH |
126 |