summaryrefslogtreecommitdiff
path: root/src/common/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/thread.h')
-rw-r--r--src/common/thread.h156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/common/thread.h b/src/common/thread.h
new file mode 100644
index 000000000..6384a44a1
--- /dev/null
+++ b/src/common/thread.h
@@ -0,0 +1,156 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#ifndef _THREAD_H_
6#define _THREAD_H_
7
8#include "std_condition_variable.h"
9#include "std_mutex.h"
10#include "std_thread.h"
11
12// Don't include common.h here as it will break LogManager
13#include "common_types.h"
14#include <stdio.h>
15#include <string.h>
16
17// This may not be defined outside _WIN32
18#ifndef _WIN32
19#ifndef INFINITE
20#define INFINITE 0xffffffff
21#endif
22
23//for gettimeofday and struct time(spec|val)
24#include <time.h>
25#include <sys/time.h>
26#endif
27
28namespace Common
29{
30
31int CurrentThreadId();
32
33void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
34void SetCurrentThreadAffinity(u32 mask);
35
36class Event
37{
38public:
39 Event()
40 : is_set(false)
41 {};
42
43 void Set()
44 {
45 std::lock_guard<std::mutex> lk(m_mutex);
46 if (!is_set)
47 {
48 is_set = true;
49 m_condvar.notify_one();
50 }
51 }
52
53 void Wait()
54 {
55 std::unique_lock<std::mutex> lk(m_mutex);
56 m_condvar.wait(lk, IsSet(this));
57 is_set = false;
58 }
59
60 void Reset()
61 {
62 std::unique_lock<std::mutex> lk(m_mutex);
63 // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
64 is_set = false;
65 }
66
67private:
68 class IsSet
69 {
70 public:
71 IsSet(const Event* ev)
72 : m_event(ev)
73 {}
74
75 bool operator()()
76 {
77 return m_event->is_set;
78 }
79
80 private:
81 const Event* const m_event;
82 };
83
84 volatile bool is_set;
85 std::condition_variable m_condvar;
86 std::mutex m_mutex;
87};
88
89// TODO: doesn't work on windows with (count > 2)
90class Barrier
91{
92public:
93 Barrier(size_t count)
94 : m_count(count), m_waiting(0)
95 {}
96
97 // block until "count" threads call Sync()
98 bool Sync()
99 {
100 std::unique_lock<std::mutex> lk(m_mutex);
101
102 // TODO: broken when next round of Sync()s
103 // is entered before all waiting threads return from the notify_all
104
105 if (m_count == ++m_waiting)
106 {
107 m_waiting = 0;
108 m_condvar.notify_all();
109 return true;
110 }
111 else
112 {
113 m_condvar.wait(lk, IsDoneWating(this));
114 return false;
115 }
116 }
117
118private:
119 class IsDoneWating
120 {
121 public:
122 IsDoneWating(const Barrier* bar)
123 : m_bar(bar)
124 {}
125
126 bool operator()()
127 {
128 return (0 == m_bar->m_waiting);
129 }
130
131 private:
132 const Barrier* const m_bar;
133 };
134
135 std::condition_variable m_condvar;
136 std::mutex m_mutex;
137 const size_t m_count;
138 volatile size_t m_waiting;
139};
140
141void SleepCurrentThread(int ms);
142void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
143
144// Use this function during a spin-wait to make the current thread
145// relax while another thread is working. This may be more efficient
146// than using events because event functions use kernel calls.
147inline void YieldCPU()
148{
149 std::this_thread::yield();
150}
151
152void SetCurrentThreadName(const char *name);
153
154} // namespace Common
155
156#endif // _THREAD_H_