aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/common/thread.h
diff options
context:
space:
mode:
authorGravatar bunnei <ericbunnie@gmail.com>2014-04-08 19:25:03 -0400
committerGravatar bunnei <ericbunnie@gmail.com>2014-04-08 19:25:03 -0400
commit63e46abdb8764bc97e91bae862c8d461e61b1965 (patch)
treee73f4aa25d7b4015a265e7bbfb6004dab7561027 /src/common/thread.h
parent03c245345e1f319da5007c15019ed54432029fb8 (diff)
got rid of 'src' folders in each sub-project
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 00000000..6384a44a
--- /dev/null
+++ b/src/common/thread.h
@@ -0,0 +1,156 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#ifndef _THREAD_H_
+#define _THREAD_H_
+
+#include "std_condition_variable.h"
+#include "std_mutex.h"
+#include "std_thread.h"
+
+// Don't include common.h here as it will break LogManager
+#include "common_types.h"
+#include <stdio.h>
+#include <string.h>
+
+// This may not be defined outside _WIN32
+#ifndef _WIN32
+#ifndef INFINITE
+#define INFINITE 0xffffffff
+#endif
+
+//for gettimeofday and struct time(spec|val)
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+namespace Common
+{
+
+int CurrentThreadId();
+
+void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
+void SetCurrentThreadAffinity(u32 mask);
+
+class Event
+{
+public:
+ Event()
+ : is_set(false)
+ {};
+
+ void Set()
+ {
+ std::lock_guard<std::mutex> lk(m_mutex);
+ if (!is_set)
+ {
+ is_set = true;
+ m_condvar.notify_one();
+ }
+ }
+
+ void Wait()
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+ m_condvar.wait(lk, IsSet(this));
+ is_set = false;
+ }
+
+ void Reset()
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+ // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
+ is_set = false;
+ }
+
+private:
+ class IsSet
+ {
+ public:
+ IsSet(const Event* ev)
+ : m_event(ev)
+ {}
+
+ bool operator()()
+ {
+ return m_event->is_set;
+ }
+
+ private:
+ const Event* const m_event;
+ };
+
+ volatile bool is_set;
+ std::condition_variable m_condvar;
+ std::mutex m_mutex;
+};
+
+// TODO: doesn't work on windows with (count > 2)
+class Barrier
+{
+public:
+ Barrier(size_t count)
+ : m_count(count), m_waiting(0)
+ {}
+
+ // block until "count" threads call Sync()
+ bool Sync()
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+
+ // TODO: broken when next round of Sync()s
+ // is entered before all waiting threads return from the notify_all
+
+ if (m_count == ++m_waiting)
+ {
+ m_waiting = 0;
+ m_condvar.notify_all();
+ return true;
+ }
+ else
+ {
+ m_condvar.wait(lk, IsDoneWating(this));
+ return false;
+ }
+ }
+
+private:
+ class IsDoneWating
+ {
+ public:
+ IsDoneWating(const Barrier* bar)
+ : m_bar(bar)
+ {}
+
+ bool operator()()
+ {
+ return (0 == m_bar->m_waiting);
+ }
+
+ private:
+ const Barrier* const m_bar;
+ };
+
+ std::condition_variable m_condvar;
+ std::mutex m_mutex;
+ const size_t m_count;
+ volatile size_t m_waiting;
+};
+
+void SleepCurrentThread(int ms);
+void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
+
+// Use this function during a spin-wait to make the current thread
+// relax while another thread is working. This may be more efficient
+// than using events because event functions use kernel calls.
+inline void YieldCPU()
+{
+ std::this_thread::yield();
+}
+
+void SetCurrentThreadName(const char *name);
+
+} // namespace Common
+
+#endif // _THREAD_H_