summaryrefslogtreecommitdiff
path: root/include/threadengines/threadengine_win32.h
blob: 2fdcac5650ccb400bdb214886889fd35d7eee739 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * InspIRCd -- Internet Relay Chat Daemon
 *
 *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
 *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
 *
 * This file is part of InspIRCd.  InspIRCd is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 2.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#ifndef THREADENGINE_WIN32_H
#define THREADENGINE_WIN32_H

#include "config.h"
#include "base.h"

class Thread;

/** The ThreadEngine class has the responsibility of initialising
 * Thread derived classes. It does this by creating operating system
 * level threads which are then associated with the class transparently.
 * This allows Thread classes to be derived without needing to know how
 * the OS implements threads. You should ensure that any sections of code
 * that use threads are threadsafe and do not interact with any other
 * parts of the code which are NOT known threadsafe! If you really MUST
 * access non-threadsafe code from a Thread, use the Mutex class to wrap
 * access to the code carefully.
 */
class CoreExport ThreadEngine
{
 public:

	ThreadEngine();

	virtual ~ThreadEngine();

	static DWORD WINAPI Entry(void* parameter);

	/** Create a new thread. This takes an already allocated
	  * Thread* pointer and initializes it to use this threading
	  * engine. On failure, this function may throw a CoreException.
	  * @param thread_to_init Pointer to a newly allocated Thread
	  * derived object.
	  */
	void Start(Thread* thread_to_init);

	/** Returns the thread engine's name for display purposes
	 * @return The thread engine name
	 */
	const std::string GetName()
	{
		return "windows-thread";
	}
};

class CoreExport ThreadData
{
 public:
	HANDLE handle;
	void FreeThread(Thread* toFree);
};

/** The Mutex class represents a mutex, which can be used to keep threads
 * properly synchronised. Use mutexes sparingly, as they are a good source
 * of thread deadlocks etc, and should be avoided except where absolutely
 * neccessary. Note that the internal behaviour of the mutex varies from OS
 * to OS depending on the thread engine, for example in windows a Mutex
 * in InspIRCd uses critical sections, as they are faster and simpler to
 * manage.
 */
class CoreExport Mutex
{
 private:
	CRITICAL_SECTION wutex;
 public:
	Mutex()
	{
		InitializeCriticalSection(&wutex);
	}
	void Lock()
	{
		EnterCriticalSection(&wutex);
	}
	void Unlock()
	{
		LeaveCriticalSection(&wutex);
	}
	~Mutex()
	{
		DeleteCriticalSection(&wutex);
	}
};

class ThreadQueueData
{
	CRITICAL_SECTION mutex;
	HANDLE event;
 public:
	ThreadQueueData()
	{
		event = CreateEvent(NULL, false, false, NULL);
		if (event == NULL)
			throw CoreException("CreateEvent() failed in ThreadQueueData::ThreadQueueData()!");
		InitializeCriticalSection(&mutex);
	}

	~ThreadQueueData()
	{
		CloseHandle(event);
		DeleteCriticalSection(&mutex);
	}

	void Lock()
	{
		EnterCriticalSection(&mutex);
	}

	void Unlock()
	{
		LeaveCriticalSection(&mutex);
	}

	void Wakeup()
	{
		PulseEvent(event);
	}

	void Wait()
	{
		LeaveCriticalSection(&mutex);
		WaitForSingleObject(event, INFINITE);
		EnterCriticalSection(&mutex);
	}
};

class ThreadSignalData
{
 public:
	int connFD;
	ThreadSignalData()
	{
		connFD = -1;
	}
};

#endif