threading.h (3413B)
1 // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #pragma once 5 #include "types.h" 6 7 #if defined(__APPLE__) 8 #include <mach/semaphore.h> 9 #elif !defined(_WIN32) 10 #include <semaphore.h> 11 #endif 12 13 #include <atomic> 14 #include <functional> 15 16 namespace Threading { 17 extern u64 GetThreadCpuTime(); 18 extern u64 GetThreadTicksPerSecond(); 19 20 /// Set the name of the current thread 21 extern void SetNameOfCurrentThread(const char* name); 22 23 // Releases a timeslice to other threads. 24 extern void Timeslice(); 25 26 // -------------------------------------------------------------------------------------- 27 // ThreadHandle 28 // -------------------------------------------------------------------------------------- 29 // Abstracts an OS's handle to a thread, closing the handle when necessary. Currently, 30 // only used for getting the CPU time for a thread. 31 // 32 class ThreadHandle 33 { 34 public: 35 ThreadHandle(); 36 ThreadHandle(ThreadHandle&& handle); 37 ThreadHandle(const ThreadHandle& handle); 38 ~ThreadHandle(); 39 40 /// Returns a new handle for the calling thread. 41 static ThreadHandle GetForCallingThread(); 42 43 ThreadHandle& operator=(ThreadHandle&& handle); 44 ThreadHandle& operator=(const ThreadHandle& handle); 45 46 operator void*() const { return m_native_handle; } 47 operator bool() const { return (m_native_handle != nullptr); } 48 49 /// Returns the amount of CPU time consumed by the thread, at the GetThreadTicksPerSecond() frequency. 50 u64 GetCPUTime() const; 51 52 /// Sets the affinity for a thread to the specified processors. 53 /// Obviously, only works up to 64 processors. 54 bool SetAffinity(u64 processor_mask) const; 55 56 protected: 57 void* m_native_handle = nullptr; 58 59 // We need the thread ID for affinity adjustments on Linux. 60 #if defined(__linux__) 61 unsigned int m_native_id = 0; 62 #endif 63 }; 64 65 // -------------------------------------------------------------------------------------- 66 // Thread 67 // -------------------------------------------------------------------------------------- 68 // Abstracts a native thread in a lightweight manner. Provides more functionality than 69 // std::thread (allowing stack size adjustments). 70 // 71 class Thread : public ThreadHandle 72 { 73 public: 74 using EntryPoint = std::function<void()>; 75 76 Thread(); 77 Thread(Thread&& thread); 78 Thread(const Thread&) = delete; 79 Thread(EntryPoint func); 80 ~Thread(); 81 82 ThreadHandle& operator=(Thread&& thread); 83 ThreadHandle& operator=(const Thread& handle) = delete; 84 85 ALWAYS_INLINE bool Joinable() const { return (m_native_handle != nullptr); } 86 ALWAYS_INLINE u32 GetStackSize() const { return m_stack_size; } 87 88 /// Sets the stack size for the thread. Do not call if the thread has already been started. 89 void SetStackSize(u32 size); 90 91 bool Start(EntryPoint func); 92 void Detach(); 93 void Join(); 94 95 protected: 96 #ifdef _WIN32 97 static unsigned __stdcall ThreadProc(void* param); 98 #else 99 static void* ThreadProc(void* param); 100 #endif 101 102 u32 m_stack_size = 0; 103 }; 104 105 /// A semaphore that may not have a fast userspace path 106 /// (Used in other semaphore-based algorithms where the semaphore is just used for its thread sleep/wake ability) 107 class KernelSemaphore 108 { 109 #if defined(_WIN32) 110 void* m_sema; 111 #elif defined(__APPLE__) 112 semaphore_t m_sema; 113 #else 114 sem_t m_sema; 115 #endif 116 public: 117 KernelSemaphore(); 118 ~KernelSemaphore(); 119 void Post(); 120 void Wait(); 121 bool TryWait(); 122 }; 123 124 } // namespace Threading