Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : #if defined(_WIN32)
4 : :
5 : : #include <windows.h>
6 : :
7 : : struct function_pointer_wrapper /*have this struct at global level*/
8 : : {
9 : : static void (*fiber_callback)(void *);
10 : : static void __stdcall execute_fiber(void* parameter) { return fiber_callback(parameter); }
11 : :
12 : : static unsigned long (*thread_callback)(void*);
13 : 115 : static unsigned long __stdcall execute_thread(void* parameter) { return thread_callback(parameter); }
14 : : };
15 : :
16 : : void (*function_pointer_wrapper::fiber_callback)(void*) = nullptr;
17 : : unsigned long (*function_pointer_wrapper::thread_callback)(void*) = nullptr;
18 : :
19 : : template <typename functor>
20 : : bool run_as_fiber(functor &&callback) {
21 : : struct fiber_wrapper {
22 : : functor &callback;
23 : : void *original;
24 : : bool result;
25 : :
26 : : void execute() {
27 : : result = callback();
28 : : SwitchToFiber(original);
29 : : }
30 : :
31 : : } wrapper{callback, nullptr, false};
32 : :
33 : : function_pointer_wrapper::fiber_callback = [](void *parameter){
34 : : reinterpret_cast<fiber_wrapper*>(parameter)->execute();
35 : : };
36 : : auto fiber = CreateFiberEx(16*1024*1024, 16*1024*1024, 0, &function_pointer_wrapper::execute_fiber, &wrapper);
37 : :
38 : : if (!fiber) {
39 : : return callback();
40 : : }
41 : :
42 : : void* main_thread = ConvertThreadToFiber(nullptr);
43 : : if (!main_thread && GetLastError() != ERROR_ALREADY_FIBER) {
44 : : return callback();
45 : : }
46 : : wrapper.original = GetCurrentFiber();
47 : : SwitchToFiber(fiber);
48 : : DeleteFiber(fiber);
49 : : if (main_thread) {
50 : : ConvertFiberToThread();
51 : : }
52 : : return wrapper.result;
53 : : }
54 : :
55 : :
56 : : template <typename functor>
57 : 115 : bool run_as_thread(functor&& callback) {
58 : : struct thread_wrapper {
59 : : functor& callback;
60 : : bool result;
61 : :
62 : 115 : unsigned long execute() {
63 : 115 : result = callback();
64 [ + + ]: 115 : return (result ? 0 : -1);
65 : : }
66 : :
67 : 115 : } wrapper{ callback, false };
68 : :
69 : 115 : function_pointer_wrapper::thread_callback = [](void* parameter) {
70 : 115 : return reinterpret_cast<thread_wrapper*>(parameter)->execute();
71 : : };
72 : :
73 : 115 : auto thread = CreateThread(NULL, 16 * 1024 * 1024, &function_pointer_wrapper::execute_thread, &wrapper, 0, NULL);
74 : :
75 [ - + ]: 115 : if (!thread) {
76 : 0 : return callback();
77 : : }
78 : :
79 : 115 : WaitForSingleObject(thread, INFINITE);
80 : :
81 : 115 : CloseHandle(thread);
82 : :
83 : 115 : return wrapper.result;
84 : : }
85 : :
86 : : char* stack_bottom = nullptr;
87 : 335 : void init_stack_use_check() {
88 : : MEMORY_BASIC_INFORMATION mbi;
89 : : char stackvar;
90 : 335 : VirtualQuery(&stackvar, &mbi, sizeof(mbi));
91 : 335 : stack_bottom = (char*)mbi.AllocationBase;
92 : 335 : }
93 : 330 : void deinit_stack_use_check() {
94 : 330 : stack_bottom = nullptr;
95 : 330 : }
96 : 61552 : bool have_enough_stack_left() {
97 : : char stackvar;
98 [ + - + + ]: 61552 : return stack_bottom == nullptr || (&stackvar - stack_bottom) >= 32768;
99 : : }
100 : : #endif
|