]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/threadengines/threadengine_pthread.cpp
Update all wiki links to point to the new wiki. This was done automatically with...
[user/henk/code/inspircd.git] / src / threadengines / threadengine_pthread.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *          the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "threadengines/threadengine_pthread.h"
16 #include <pthread.h>
17 #include <signal.h>
18
19 pthread_mutex_t MyMutex = PTHREAD_MUTEX_INITIALIZER;
20
21 PThreadEngine::PThreadEngine(InspIRCd* Instance) : ThreadEngine(Instance)
22 {
23 }
24
25 void PThreadEngine::Create(Thread* thread_to_init)
26 {
27         pthread_attr_t attribs;
28         pthread_attr_init(&attribs);
29         pthread_attr_setdetachstate(&attribs, PTHREAD_CREATE_JOINABLE);
30         pthread_t* MyPThread = new pthread_t;
31
32         /* Create a thread in a mutex. This prevents whacking the member value NewThread,
33          * and also prevents recursive creation of threads by mistake (instead, the thread
34          * will just deadlock itself)
35          */
36         Mutex(true);
37
38         if (pthread_create(MyPThread, &attribs, PThreadEngine::Entry, (void*)this) != 0)
39         {
40                 delete MyPThread;
41                 Mutex(false);
42                 throw CoreException("Unable to create new PThreadEngine: " + std::string(strerror(errno)));
43         }
44
45         pthread_attr_destroy(&attribs);
46
47         NewThread = thread_to_init;
48         NewThread->Creator = this;
49         NewThread->Extend("pthread", MyPThread);
50
51         /* Always unset a mutex if you set it */
52         Mutex(false);
53
54         /* Wait for the PThreadEngine::Run method to take a copy of the
55          * pointer and clear this member value
56          */
57         while (NewThread)
58                 usleep(1000);
59 }
60
61 PThreadEngine::~PThreadEngine()
62 {
63 }
64
65 void PThreadEngine::Run()
66 {
67         /* Take a copy of the member value, then clear it. Do this
68          * in a mutex so that we can be sure nothing else is looking
69          * at it.
70          */
71         Mutex(true);
72         Thread* nt = NewThread;
73         NewThread = NULL;
74         Mutex(false);
75         /* Now we have our own safe copy, call the object on it */
76         nt->Run();
77 }
78
79 bool PThreadEngine::Mutex(bool enable)
80 {
81         if (enable)
82                 pthread_mutex_lock(&MyMutex);
83         else
84                 pthread_mutex_unlock(&MyMutex);
85
86         return false;
87 }
88
89 void* PThreadEngine::Entry(void* parameter)
90 {
91         /* Recommended by nenolod, signal safety on a per-thread basis */
92         sigset_t set;
93         sigemptyset(&set);
94         sigaddset(&set, SIGPIPE);
95         if(pthread_sigmask(SIG_BLOCK, &set, NULL))
96                 signal(SIGPIPE, SIG_IGN);
97
98         ThreadEngine * pt = (ThreadEngine*)parameter;
99         pt->Run();
100         return NULL;
101 }
102
103 void PThreadEngine::FreeThread(Thread* thread)
104 {
105         pthread_t* pthread = NULL;
106         if (thread->GetExt("pthread", pthread))
107         {
108                 thread->SetExitFlag();
109                 int rc;
110                 void* status;
111                 rc = pthread_join(*pthread, &status);
112                 delete pthread;
113         }
114 }
115
116 MutexFactory::MutexFactory(InspIRCd* Instance) : ServerInstance(Instance)
117 {
118 }
119
120 Mutex* MutexFactory::CreateMutex()
121 {
122         return new PosixMutex(this->ServerInstance);
123 }
124
125 PosixMutex::PosixMutex(InspIRCd* Instance) : Mutex(Instance)
126 {
127         pthread_mutex_init(&putex, NULL);
128 }
129
130 PosixMutex::~PosixMutex()
131 {
132         pthread_mutex_destroy(&putex);
133 }
134
135 void PosixMutex::Enable(bool enable)
136 {
137         if (enable)
138                 pthread_mutex_lock(&putex);
139         else
140                 pthread_mutex_unlock(&putex);
141 }