1 module eventcore.core;
2 
3 public import eventcore.driver;
4 
5 import eventcore.drivers.posix.cfrunloop;
6 import eventcore.drivers.posix.epoll;
7 import eventcore.drivers.posix.kqueue;
8 import eventcore.drivers.posix.select;
9 import eventcore.drivers.libasync;
10 import eventcore.drivers.winapi.driver;
11 import eventcore.internal.utils : mallocT, freeT;
12 
13 version (EventcoreEpollDriver) alias NativeEventDriver = EpollEventDriver;
14 else version (EventcoreCFRunLoopDriver) alias NativeEventDriver = CFRunLoopEventDriver;
15 else version (EventcoreKqueueDriver) alias NativeEventDriver = KqueueEventDriver;
16 else version (EventcoreWinAPIDriver) alias NativeEventDriver = WinAPIEventDriver;
17 else version (EventcoreLibasyncDriver) alias NativeEventDriver = LibasyncEventDriver;
18 else version (EventcoreSelectDriver) alias NativeEventDriver = SelectEventDriver;
19 else alias NativeEventDriver = EventDriver;
20 
21 /** Returns the event driver associated to the calling thread.
22 
23 	If no driver has been created, one will be allocated lazily. The return
24 	value is guaranteed to be non-null.
25 */
26 @property NativeEventDriver eventDriver()
27 @safe @nogc nothrow {
28 	static if (is(NativeEventDriver == EventDriver))
29 		assert(s_driver !is null, "setupEventDriver() was not called for this thread.");
30 	else {
31 		if (!s_driver) {
32 			s_driver = mallocT!NativeEventDriver;
33 		}
34 	}
35 	return s_driver;
36 }
37 
38 
39 /** Returns the event driver associated with the calling thread, if any.
40 
41 	If no driver has been created, this function will return `null`.
42 */
43 NativeEventDriver tryGetEventDriver()
44 @safe @nogc nothrow {
45 	return s_driver;
46 }
47 
48 static if (!is(NativeEventDriver == EventDriver)) {
49 	static this()
50 	{
51 		if (!s_isMainThread) {
52 			s_initCount++;
53 		}
54 	}
55 
56 	static ~this()
57 	{
58 		if (!s_isMainThread) {
59 			if (!--s_initCount) {
60 				if (s_driver) {
61 					if (s_driver.dispose())
62 						freeT(s_driver);
63 				}
64 			}
65 		}
66 	}
67 
68 	shared static this()
69 	{
70 		if (!s_initCount++) {
71 			s_isMainThread = true;
72 		}
73 	}
74 
75 	shared static ~this()
76 	{
77 		if (!--s_initCount) {
78 			if (s_driver) {
79 				if (s_driver.dispose())
80 					freeT(s_driver);
81 			}
82 		}
83 	}
84 } else {
85 	void setupEventDriver(EventDriver driver)
86 	{
87 		assert(driver !is null, "The event driver instance must be non-null.");
88 		assert(!s_driver, "Can only set up the event driver once per thread.");
89 		s_driver = driver;
90 	}
91 }
92 
93 private {
94 	NativeEventDriver s_driver;
95 	bool s_isMainThread;
96 	// keeps track of nested DRuntime initializations that happen when
97 	// (un)loading shared libaries.
98 	int s_initCount = 0;
99 }