-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdllthread.hpp
More file actions
107 lines (83 loc) · 2.55 KB
/
dllthread.hpp
File metadata and controls
107 lines (83 loc) · 2.55 KB
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
#pragma once
#ifdef _WIN32
#ifndef _WINDOWS_
# define WIN32_LEAN_AND_MEAN
# define NOMINMAX
# include <Windows.h>
#endif
#include <functional>
#include <system_error>
#include <thread>
// Unitily class. Similar to recursive_mutex, can be safely used during Dll initialization
class RTLSection {
public:
typedef RTL_CRITICAL_SECTION* native_handle_type;
RTLSection() { InitializeCriticalSection(&cs); }
~RTLSection() { DeleteCriticalSection(&cs); }
RTLSection(const RTLSection&) = delete;
RTLSection& operator=(const RTLSection&) = delete;
void lock() { EnterCriticalSection(&cs); }
bool try_lock() { return !!TryEnterCriticalSection(&cs); }
void unlock() { LeaveCriticalSection(&cs); }
native_handle_type native_handle() { return &cs; }
private:
RTL_CRITICAL_SECTION cs;
};
class dllthread {
public:
typedef DWORD id;
typedef HANDLE native_handle_type;
id get_id() const { return m_id; }
native_handle_type native_handle() const { return m_threadEnded; }
static unsigned int hardware_concurrency() { return std::thread::hardware_concurrency(); }
dllthread() { reset(*this); }
template<typename Fn, typename ...Args, typename std::enable_if<!std::is_same<typename std::decay<Fn>::type, dllthread>::value, int>::type* = nullptr>
explicit dllthread(Fn&& fn, Args&&... args) {
reset(*this);
init(std::move(std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)));
}
~dllthread();
dllthread(const dllthread&) = delete;
dllthread& operator=(const dllthread&) = delete;
dllthread(dllthread&& other) :
m_threadStarted(other.m_threadStarted),
m_threadEnded(other.m_threadEnded),
m_thread(other.m_thread),
m_id(other.m_id)
{
reset(other);
}
dllthread& operator=(dllthread&& other) {
if (joinable())
join();
m_threadStarted = other.m_threadStarted;
m_threadEnded = other.m_threadEnded;
m_id = other.m_id;
m_thread = other.m_thread;
reset(other);
return *this;
}
void swap(dllthread& other) {
std::swap(m_threadStarted, other.m_threadStarted);
std::swap(m_threadEnded, other.m_threadEnded);
std::swap(m_thread, other.m_thread);
std::swap(m_id, other.m_id);
}
bool joinable() const {
return m_threadEnded != INVALID_HANDLE_VALUE;
}
void join();
void detach();
private:
HANDLE m_threadStarted, m_threadEnded, m_thread;
DWORD m_id;
struct InitStruct;
InitStruct *m_initstruct; // in case for deadlock
static DWORD WINAPI threadstart(LPVOID param);
void init(std::function<void()>&& fn);
static void reset(dllthread& obj);
};
#else // ifdef _WIN32
#include <thread>
typedef std::thread dllthread;
#endif // ifdef _WIN32