mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
8c7a192128
Should've did this in the beginning.
124 lines
3.3 KiB
C++
124 lines
3.3 KiB
C++
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
|
|
#pragma once
|
|
#include "types.h"
|
|
|
|
#if defined(__APPLE__)
|
|
#include <mach/semaphore.h>
|
|
#elif !defined(_WIN32)
|
|
#include <semaphore.h>
|
|
#endif
|
|
|
|
#include <atomic>
|
|
#include <functional>
|
|
|
|
namespace Threading {
|
|
extern u64 GetThreadCpuTime();
|
|
extern u64 GetThreadTicksPerSecond();
|
|
|
|
/// Set the name of the current thread
|
|
extern void SetNameOfCurrentThread(const char* name);
|
|
|
|
// Releases a timeslice to other threads.
|
|
extern void Timeslice();
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// ThreadHandle
|
|
// --------------------------------------------------------------------------------------
|
|
// Abstracts an OS's handle to a thread, closing the handle when necessary. Currently,
|
|
// only used for getting the CPU time for a thread.
|
|
//
|
|
class ThreadHandle
|
|
{
|
|
public:
|
|
ThreadHandle();
|
|
ThreadHandle(ThreadHandle&& handle);
|
|
ThreadHandle(const ThreadHandle& handle);
|
|
~ThreadHandle();
|
|
|
|
/// Returns a new handle for the calling thread.
|
|
static ThreadHandle GetForCallingThread();
|
|
|
|
ThreadHandle& operator=(ThreadHandle&& handle);
|
|
ThreadHandle& operator=(const ThreadHandle& handle);
|
|
|
|
operator void*() const { return m_native_handle; }
|
|
operator bool() const { return (m_native_handle != nullptr); }
|
|
|
|
/// Returns the amount of CPU time consumed by the thread, at the GetThreadTicksPerSecond() frequency.
|
|
u64 GetCPUTime() const;
|
|
|
|
/// Sets the affinity for a thread to the specified processors.
|
|
/// Obviously, only works up to 64 processors.
|
|
bool SetAffinity(u64 processor_mask) const;
|
|
|
|
protected:
|
|
void* m_native_handle = nullptr;
|
|
|
|
// We need the thread ID for affinity adjustments on Linux.
|
|
#if defined(__linux__)
|
|
unsigned int m_native_id = 0;
|
|
#endif
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// Thread
|
|
// --------------------------------------------------------------------------------------
|
|
// Abstracts a native thread in a lightweight manner. Provides more functionality than
|
|
// std::thread (allowing stack size adjustments).
|
|
//
|
|
class Thread : public ThreadHandle
|
|
{
|
|
public:
|
|
using EntryPoint = std::function<void()>;
|
|
|
|
Thread();
|
|
Thread(Thread&& thread);
|
|
Thread(const Thread&) = delete;
|
|
Thread(EntryPoint func);
|
|
~Thread();
|
|
|
|
ThreadHandle& operator=(Thread&& thread);
|
|
ThreadHandle& operator=(const Thread& handle) = delete;
|
|
|
|
ALWAYS_INLINE bool Joinable() const { return (m_native_handle != nullptr); }
|
|
ALWAYS_INLINE u32 GetStackSize() const { return m_stack_size; }
|
|
|
|
/// Sets the stack size for the thread. Do not call if the thread has already been started.
|
|
void SetStackSize(u32 size);
|
|
|
|
bool Start(EntryPoint func);
|
|
void Detach();
|
|
void Join();
|
|
|
|
protected:
|
|
#ifdef _WIN32
|
|
static unsigned __stdcall ThreadProc(void* param);
|
|
#else
|
|
static void* ThreadProc(void* param);
|
|
#endif
|
|
|
|
u32 m_stack_size = 0;
|
|
};
|
|
|
|
/// A semaphore that may not have a fast userspace path
|
|
/// (Used in other semaphore-based algorithms where the semaphore is just used for its thread sleep/wake ability)
|
|
class KernelSemaphore
|
|
{
|
|
#if defined(_WIN32)
|
|
void* m_sema;
|
|
#elif defined(__APPLE__)
|
|
semaphore_t m_sema;
|
|
#else
|
|
sem_t m_sema;
|
|
#endif
|
|
public:
|
|
KernelSemaphore();
|
|
~KernelSemaphore();
|
|
void Post();
|
|
void Wait();
|
|
bool TryWait();
|
|
};
|
|
|
|
} // namespace Threading
|