| [111] | 1 | /* |
|---|
| 2 | PowerDNS Versatile Database Driven Nameserver |
|---|
| 3 | Copyright (C) 2002 PowerDNS.COM BV |
|---|
| 4 | |
|---|
| 5 | This program is free software; you can redistribute it and/or modify |
|---|
| 6 | it under the terms of the GNU General Public License as published by |
|---|
| 7 | the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | (at your option) any later version. |
|---|
| 9 | |
|---|
| 10 | This program is distributed in the hope that it will be useful, |
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with this program; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | */ |
|---|
| 19 | #ifndef MTASKER_HH |
|---|
| 20 | #define MTASKER_HH |
|---|
| [141] | 21 | |
|---|
| 22 | #ifdef WIN32 |
|---|
| 23 | # include "win32_mtasker.hh" |
|---|
| 24 | #else |
|---|
| 25 | |
|---|
| [111] | 26 | #include <signal.h> |
|---|
| 27 | #include <ucontext.h> |
|---|
| 28 | #include <queue> |
|---|
| 29 | #include <vector> |
|---|
| 30 | #include <map> |
|---|
| 31 | #include <time.h> |
|---|
| [547] | 32 | #include <boost/multi_index_container.hpp> |
|---|
| 33 | #include <boost/multi_index/ordered_index.hpp> |
|---|
| 34 | #include <boost/multi_index/key_extractors.hpp> |
|---|
| 35 | using namespace boost; |
|---|
| 36 | using namespace ::boost::multi_index; |
|---|
| [111] | 37 | |
|---|
| 38 | //! The main MTasker class |
|---|
| 39 | /** The main MTasker class. See the main page for more information. |
|---|
| 40 | \param EventKey Type of the key with which events are to be identified. Defaults to int. |
|---|
| 41 | \param EventVal Type of the content or value of an event. Defaults to int. Cannot be set to void. |
|---|
| 42 | \note The EventKey needs to have an operator< defined because it is used as the key of an associative array |
|---|
| 43 | */ |
|---|
| 44 | template<class EventKey=int, class EventVal=int> class MTasker |
|---|
| 45 | { |
|---|
| 46 | private: |
|---|
| 47 | ucontext_t d_kernel; |
|---|
| 48 | std::queue<int> d_runQueue; |
|---|
| 49 | std::queue<int> d_zombiesQueue; |
|---|
| 50 | |
|---|
| 51 | struct Waiter |
|---|
| 52 | { |
|---|
| [547] | 53 | EventKey key; |
|---|
| [111] | 54 | ucontext_t *context; |
|---|
| 55 | time_t ttd; |
|---|
| 56 | int tid; |
|---|
| 57 | }; |
|---|
| 58 | |
|---|
| [547] | 59 | // typedef std::map<EventKey,Waiter> waiters_t; |
|---|
| [576] | 60 | struct KeyTag {}; |
|---|
| [547] | 61 | typedef multi_index_container< |
|---|
| 62 | Waiter, |
|---|
| 63 | indexed_by < |
|---|
| 64 | ordered_unique<member<Waiter,EventKey,&Waiter::key> >, |
|---|
| [576] | 65 | ordered_non_unique<tag<KeyTag>, member<Waiter,time_t,&Waiter::ttd> > |
|---|
| [547] | 66 | > |
|---|
| 67 | > waiters_t; |
|---|
| 68 | |
|---|
| [111] | 69 | waiters_t d_waiters; |
|---|
| [547] | 70 | |
|---|
| [442] | 71 | typedef std::map<int,pair<ucontext_t*,string> > mthreads_t; |
|---|
| 72 | mthreads_t d_threads; |
|---|
| [111] | 73 | int d_tid; |
|---|
| 74 | int d_maxtid; |
|---|
| 75 | size_t d_stacksize; |
|---|
| 76 | |
|---|
| 77 | EventVal d_waitval; |
|---|
| 78 | enum {Error=-1,TimeOut=0,Answer} d_waitstatus; |
|---|
| 79 | |
|---|
| 80 | public: |
|---|
| 81 | //! Constructor |
|---|
| 82 | /** Constructor with a small default stacksize. If any of your threads exceeds this stack, your application will crash. |
|---|
| 83 | This limit applies solely to the stack, the heap is not limited in any way. If threads need to allocate a lot of data, |
|---|
| 84 | the use of new/delete is suggested. |
|---|
| 85 | */ |
|---|
| 86 | MTasker(size_t stacksize=8192) : d_stacksize(stacksize) |
|---|
| 87 | { |
|---|
| 88 | d_maxtid=0; |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | typedef void tfunc_t(void *); //!< type of the pointer that starts a thread |
|---|
| 92 | int waitEvent(const EventKey &key, EventVal *val=0, unsigned int timeout=0); |
|---|
| 93 | void yield(); |
|---|
| 94 | int sendEvent(const EventKey& key, const EventVal* val=0); |
|---|
| 95 | void getEvents(std::vector<EventKey>& events); |
|---|
| [442] | 96 | void makeThread(tfunc_t *start, void* val, const string& name=""); |
|---|
| [111] | 97 | bool schedule(); |
|---|
| 98 | bool noProcesses(); |
|---|
| [234] | 99 | unsigned int numProcesses(); |
|---|
| [135] | 100 | int getTid(); |
|---|
| [442] | 101 | void setTitle(const string& name) |
|---|
| 102 | { |
|---|
| 103 | d_threads[d_tid].second=name; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| [111] | 106 | private: |
|---|
| 107 | static void threadWrapper(MTasker *self, tfunc_t *tf, int tid, void* val); |
|---|
| 108 | }; |
|---|
| 109 | #include "mtasker.cc" |
|---|
| [141] | 110 | |
|---|
| 111 | #endif // WIN32 |
|---|
| 112 | #endif // MTASKER_HH |
|---|
| 113 | |
|---|