comparison foosdk/sdk/pfc/threads.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 #include <functional>
4
5 #ifdef _WIN32
6 #include <process.h>
7 #else
8 #include <pthread.h>
9 #endif
10 namespace pfc {
11 unsigned getOptimalWorkerThreadCount();
12 unsigned getOptimalWorkerThreadCountEx(size_t taskCountLimit);
13
14 //! IMPORTANT: all classes derived from thread must call waitTillDone() in their destructor, to avoid object destruction during a virtual function call!
15 class thread {
16 public:
17 #ifdef _WIN32
18 typedef HANDLE handle_t;
19 #else
20 typedef pthread_t handle_t;
21 #endif
22 // Returns a psuedo-handle meant only for local use, see win32 GetCurrentThread() semantics
23 static handle_t handleToCurrent();
24
25 struct arg_t {
26 #ifdef _WIN32
27 int winThreadPriority = 0; // THREAD_PRIORITY_NORMAL
28 #endif
29 #ifdef __APPLE__
30 // see: pthread_set_qos_class_self_np
31 int appleThreadQOS = 0; // QOS_CLASS_UNSPECIFIED
32 int appleRealtivePriority = 0; // valid only if appleThreadQOS is set
33 #endif
34 #ifndef _WIN32
35 int nixSchedPolicy = -1; // not set - cannot use 0 because SCHED_OTHER is 0 on Linux
36 sched_param nixSchedParam = {}; // valid only if nixSchedPolicy is set
37 #endif
38 };
39
40 static arg_t argDefault();
41 static arg_t argCurrentThread();
42 static arg_t argBackground();
43 static arg_t argHighPriority();
44 static arg_t argPlayback();
45 static arg_t argUserInitiated();
46 #ifdef _WIN32
47 static arg_t argWinPriority(int priority);
48 #endif
49 #ifdef __APPLE__
50 static arg_t argAppleQOS(int qos);
51 #endif
52 #ifndef _WIN32
53 static arg_t argNixPriority( int policy, int percent );
54 #endif
55
56 //! Critical error handler function, never returns
57 PFC_NORETURN static void couldNotCreateThread();
58
59 thread();
60 ~thread() {PFC_ASSERT(!isActive()); waitTillDone();}
61 void start( arg_t const & arg = argCurrentThread() );
62 //! Valid thread object (created and not joined)?
63 bool isActive() const;
64 //! Joins the thread: blocks until complete, releases resources. \n
65 //! After waitTillDone() returns, isActive() becomes false. \n
66 //! No-op if thread not started.
67 void waitTillDone() {close();}
68 #ifdef _WIN32
69 void winStart(int priority, DWORD * outThreadID);
70 HANDLE winThreadHandle() { return m_thread; }
71 #else
72 pthread_t posixThreadHandle() { return m_thread; }
73 #endif
74 #ifdef __APPLE__
75 static void appleStartThreadPrologue();
76 #endif
77
78 static void setCurrentPriority(arg_t const&);
79 protected:
80 virtual void threadProc() {PFC_ASSERT(!"Stub thread entry - should not get here");}
81 private:
82 void close();
83 #ifdef _WIN32
84 static unsigned CALLBACK g_entry(void* p_instance);
85 #else
86 static void * g_entry( void * arg );
87 #endif
88 void entry();
89
90 handle_t m_thread;
91 #ifndef _WIN32
92 bool m_threadValid; // there is no invalid pthread_t, so we keep a separate 'valid' flag
93 #endif
94
95 PFC_CLASS_NOT_COPYABLE_EX(thread)
96 };
97
98 //! Thread class using lambda entrypoint rather than function override
99 class thread2 : public thread {
100 public:
101 ~thread2() { waitTillDone(); }
102 void startHere(std::function<void()> e);
103 void startHere(arg_t const& arg, std::function<void()> e);
104 void setEntry(std::function<void()> e);
105 private:
106 void threadProc();
107
108 std::function<void()> m_entryPoint;
109 };
110
111 void splitThread(std::function<void() > f);
112 void splitThread(pfc::thread::arg_t const & arg, std::function<void()> f);
113
114 //! Apple specific; executes the function in a release pool scope. \n
115 //! On non Apple platforms it just invokes the function.
116 void inAutoReleasePool(std::function<void()> f);
117 }