1 /**
2 	WinAPI based event driver implementation.
3 
4 	This driver uses overlapped I/O to model asynchronous I/O operations
5 	efficiently. The driver's event loop processes UI messages, so that
6 	it integrates with GUI applications transparently.
7 */
8 module eventcore.drivers.winapi.driver;
9 
10 version (Windows):
11 
12 import eventcore.driver;
13 import eventcore.drivers.timer;
14 import eventcore.drivers.winapi.core;
15 import eventcore.drivers.winapi.dns;
16 import eventcore.drivers.winapi.events;
17 import eventcore.drivers.winapi.files;
18 import eventcore.drivers.winapi.pipes;
19 import eventcore.drivers.winapi.processes;
20 import eventcore.drivers.winapi.signals;
21 import eventcore.drivers.winapi.sockets;
22 import eventcore.drivers.winapi.watchers;
23 import eventcore.internal.utils : mallocT, freeT;
24 import core.sys.windows.windows;
25 
26 static assert(HANDLE.sizeof <= FD.BaseType.sizeof);
27 static assert(FD(cast(size_t)INVALID_HANDLE_VALUE, 0) == FD.init);
28 
29 
30 final class WinAPIEventDriver : EventDriver {
31 	private {
32 		WinAPIEventDriverCore m_core;
33 		WinAPIEventDriverFiles m_files;
34 		WinAPIEventDriverSockets m_sockets;
35 		WinAPIEventDriverDNS m_dns;
36 		LoopTimeoutTimerDriver m_timers;
37 		WinAPIEventDriverEvents m_events;
38 		WinAPIEventDriverSignals m_signals;
39 		WinAPIEventDriverWatchers m_watchers;
40 		WinAPIEventDriverProcesses m_processes;
41 		WinAPIEventDriverPipes m_pipes;
42 	}
43 
44 	static WinAPIEventDriver threadInstance;
45 
46 	this()
47 	@safe nothrow @nogc {
48 		assert(threadInstance is null);
49 		threadInstance = this;
50 
51 		import std.exception : enforce;
52 
53 		WSADATA wd;
54 
55 		auto res = () @trusted { return WSAStartup(0x0202, &wd); } ();
56 		assert(res == 0, "Failed to initialize WinSock");
57 
58 		m_signals = mallocT!WinAPIEventDriverSignals();
59 		m_timers = mallocT!LoopTimeoutTimerDriver();
60 		m_core = mallocT!WinAPIEventDriverCore(m_timers);
61 		m_events = mallocT!WinAPIEventDriverEvents(m_core);
62 		m_files = mallocT!WinAPIEventDriverFiles(m_core);
63 		m_sockets = mallocT!WinAPIEventDriverSockets(m_core);
64 		m_pipes = mallocT!WinAPIEventDriverPipes();
65 		m_dns = mallocT!WinAPIEventDriverDNS();
66 		m_watchers = mallocT!WinAPIEventDriverWatchers(m_core);
67 		m_processes = mallocT!WinAPIEventDriverProcesses();
68 	}
69 
70 @safe: /*@nogc:*/ nothrow:
71 
72 	override @property inout(WinAPIEventDriverCore) core() inout { return m_core; }
73 	override @property shared(inout(WinAPIEventDriverCore)) core() inout shared { return m_core; }
74 	override @property inout(WinAPIEventDriverFiles) files() inout { return m_files; }
75 	override @property inout(WinAPIEventDriverSockets) sockets() inout { return m_sockets; }
76 	override @property inout(WinAPIEventDriverDNS) dns() inout { return m_dns; }
77 	override @property inout(LoopTimeoutTimerDriver) timers() inout { return m_timers; }
78 	override @property inout(WinAPIEventDriverEvents) events() inout { return m_events; }
79 	override @property shared(inout(WinAPIEventDriverEvents)) events() inout shared { return m_events; }
80 	override @property inout(WinAPIEventDriverSignals) signals() inout { return m_signals; }
81 	override @property inout(WinAPIEventDriverWatchers) watchers() inout { return m_watchers; }
82 	override @property inout(WinAPIEventDriverProcesses) processes() inout { return m_processes; }
83 	override @property inout(WinAPIEventDriverPipes) pipes() inout { return m_pipes; }
84 
85 	override bool dispose()
86 	{
87 		if (!m_events) return true;
88 
89 		if (m_core.checkForLeakedHandles()) return false;
90 		if (m_events.checkForLeakedHandles()) return false;
91 		if (m_sockets.checkForLeakedHandles()) return false;
92 
93 		m_events.dispose();
94 		m_core.dispose();
95 		assert(threadInstance !is null);
96 		threadInstance = null;
97 
98 		try () @trusted {
99 			freeT(m_processes);
100 			freeT(m_watchers);
101 			freeT(m_dns);
102 			freeT(m_pipes);
103 			freeT(m_sockets);
104 			freeT(m_files);
105 			freeT(m_events);
106 			freeT(m_core);
107 			freeT(m_timers);
108 			freeT(m_signals);
109 		} ();
110 		catch (Exception e) assert(false, e.msg);
111 
112 		return true;
113 	}
114 }