]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/threadengines/threadengine_pthread.cpp
a4a47f8fa37784b10d0c3ef7dc158cd6e753bb84
[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 #include <fcntl.h>
19
20 ThreadEngine::ThreadEngine(InspIRCd* Instance)
21 {
22 }
23
24 static void* entry_point(void* parameter)
25 {
26         /* Recommended by nenolod, signal safety on a per-thread basis */
27         sigset_t set;
28         sigemptyset(&set);
29         sigaddset(&set, SIGPIPE);
30         pthread_sigmask(SIG_BLOCK, &set, NULL);
31
32         Thread* pt = static_cast<Thread*>(parameter);
33         pt->Run();
34         return parameter;
35 }
36
37
38 void ThreadEngine::Start(Thread* thread)
39 {
40         ThreadData* data = new ThreadData;
41         thread->state = data;
42
43         if (pthread_create(&data->pthread_id, NULL, entry_point, thread) != 0)
44         {
45                 thread->state = NULL;
46                 delete data;
47                 throw CoreException("Unable to create new thread: " + std::string(strerror(errno)));
48         }
49 }
50
51 ThreadEngine::~ThreadEngine()
52 {
53 }
54
55 void ThreadData::FreeThread(Thread* thread)
56 {
57         thread->SetExitFlag();
58         pthread_join(pthread_id, NULL);
59 }
60
61 #ifdef HAS_EVENTFD
62 #include <sys/eventfd.h>
63
64 class ThreadSignalSocket : public BufferedSocket
65 {
66         SocketThread* parent;
67  public:
68         ThreadSignalSocket(SocketThread* p, int newfd) : BufferedSocket(newfd), parent(p) {}
69
70         ~ThreadSignalSocket()
71         {
72         }
73
74         void Notify()
75         {
76                 eventfd_write(fd, 1);
77         }
78
79         void OnDataReady()
80         {
81                 recvq.clear();
82                 parent->OnNotify();
83         }
84
85         void OnError(BufferedSocketError)
86         {
87         }
88 };
89
90 SocketThread::SocketThread(InspIRCd* SI)
91 {
92         int fd = eventfd(0, O_NONBLOCK);
93         if (fd < 0)
94                 throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
95         signal.sock = new ThreadSignalSocket(this, fd);
96 }
97 #else
98
99 class ThreadSignalSocket : public BufferedSocket
100 {
101         SocketThread* parent;
102         int send_fd;
103  public:
104         ThreadSignalSocket(SocketThread* p, int recvfd, int sendfd) :
105                 BufferedSocket(recvfd), parent(p), send_fd(sendfd)  {}
106
107         ~ThreadSignalSocket()
108         {
109                 close(send_fd);
110         }
111
112         void Notify()
113         {
114                 char dummy = '*';
115                 write(send_fd, &dummy, 1);
116         }
117
118         void OnDataReady()
119         {
120                 recvq.clear();
121                 parent->OnNotify();
122         }
123
124         void OnError(BufferedSocketError)
125         {
126         }
127 };
128
129 SocketThread::SocketThread(InspIRCd* SI)
130 {
131         int fds[2];
132         if (pipe(fds))
133                 throw new CoreException("Could not create pipe " + std::string(strerror(errno)));
134         signal.sock = new ThreadSignalSocket(this, fds[0], fds[1]);
135 }
136 #endif
137
138 void SocketThread::NotifyParent()
139 {
140         signal.sock->Notify();
141 }
142
143 SocketThread::~SocketThread()
144 {
145 }