duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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