annotate foosdk/sdk/pfc/threads.cpp @ 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "pfc-lite.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include "pp-winapi.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 #include <sys/sysctl.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #include <sys/stat.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 #include "threads.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 #include "debug.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 #include <memory>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 #include <thread>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 #ifndef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 class c_pthread_attr {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 c_pthread_attr() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 pthread_attr_init(&a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 ~c_pthread_attr() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 pthread_attr_destroy(&a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 void apply( const pfc::thread::arg_t & arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 if ( arg.appleThreadQOS != 0 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 pthread_attr_set_qos_class_np( &a, (qos_class_t) arg.appleThreadQOS, arg.appleRealtivePriority );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 if ( arg.nixSchedPolicy >= 0 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 pthread_attr_setschedpolicy(&a, arg.nixSchedPolicy);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 pthread_attr_setschedparam(&a, &arg.nixSchedParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 pthread_attr_t a;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 c_pthread_attr( const c_pthread_attr & ) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 void operator=( const c_pthread_attr & ) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 namespace pfc {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 unsigned getOptimalWorkerThreadCount() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 return std::thread::hardware_concurrency();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 unsigned getOptimalWorkerThreadCountEx(size_t taskCountLimit) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 if (taskCountLimit <= 1) return 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 return (unsigned)pfc::min_t<size_t>(taskCountLimit,getOptimalWorkerThreadCount());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 void thread::entry() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 threadProc();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 } catch(...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 void thread::couldNotCreateThread() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 PFC_ASSERT(!"Could not create thread");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 // Something terminally wrong, better crash leaving a good debug trace
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 crash();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 thread::thread() : m_thread(INVALID_HANDLE_VALUE)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 void thread::close() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 if (isActive()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 int ctxPriority = GetThreadPriority( GetCurrentThread() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 if (ctxPriority > GetThreadPriority( m_thread ) ) SetThreadPriority( m_thread, ctxPriority );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 if (WaitForSingleObject(m_thread,INFINITE) != WAIT_OBJECT_0) couldNotCreateThread();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 CloseHandle(m_thread); m_thread = INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 bool thread::isActive() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 return m_thread != INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 static HANDLE MyBeginThread( unsigned (__stdcall * proc)(void *) , void * arg, DWORD * outThreadID, int priority) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 HANDLE thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 #ifdef PFC_WINDOWS_DESKTOP_APP
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 thread = (HANDLE)_beginthreadex(NULL, 0, proc, arg, CREATE_SUSPENDED, (unsigned int*)outThreadID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc, arg, CREATE_SUSPENDED, outThreadID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 if (thread == NULL) thread::couldNotCreateThread();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 SetThreadPriority(thread, priority);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 ResumeThread(thread);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 return thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 void thread::winStart(int priority, DWORD * outThreadID) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 close();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 m_thread = MyBeginThread(g_entry, reinterpret_cast<void*>(this), outThreadID, priority);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 void thread::start(arg_t const & arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 winStart(arg.winThreadPriority, nullptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 unsigned CALLBACK thread::g_entry(void* p_instance) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 reinterpret_cast<thread*>(p_instance)->entry(); return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 thread::thread() : m_thread(), m_threadValid() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 #ifndef __APPLE__ // Apple specific entrypoint in obj-c.mm
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 void * thread::g_entry( void * arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 reinterpret_cast<thread*>( arg )->entry();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 return NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 void thread::start(arg_t const & arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 close();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 appleStartThreadPrologue();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 pthread_t thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 c_pthread_attr attr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 pthread_attr_setdetachstate(&attr.a, PTHREAD_CREATE_JOINABLE);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 attr.apply( arg );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 if (pthread_create(&thread, &attr.a, g_entry, reinterpret_cast<void*>(this)) != 0) couldNotCreateThread();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 m_threadValid = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 m_thread = thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 void thread::close() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 if (m_threadValid) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 void * rv = NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 pthread_join( m_thread, & rv ); m_thread = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 m_threadValid = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 bool thread::isActive() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 return m_threadValid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 unsigned CALLBACK winSplitThreadProc(void* arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 auto f = reinterpret_cast<std::function<void() > *>(arg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 (*f)();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 delete f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 void * nixSplitThreadProc(void * arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 auto f = reinterpret_cast<std::function<void() > *>(arg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 inAutoReleasePool([f] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 (*f)();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 delete f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 });
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 (*f)();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 delete f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 return NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 void splitThread( std::function<void ()> f ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 splitThread( thread::argCurrentThread(), f );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 void splitThread(thread::arg_t const & arg, std::function<void() > f) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 auto arg2 = std::make_unique<std::function<void()> >(f);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 HANDLE h = MyBeginThread(winSplitThreadProc, arg2.get(), NULL, arg.winThreadPriority );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 CloseHandle(h);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 thread::appleStartThreadPrologue();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 pthread_t thread;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 c_pthread_attr attr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 attr.apply( arg );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 if (pthread_create(&thread, &attr.a, nixSplitThreadProc, arg2.get()) != 0) thread::couldNotCreateThread();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 pthread_detach(thread);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 arg2.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 #ifndef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 // Stub for non Apple
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 void inAutoReleasePool(std::function<void()> f) { f(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 void thread2::startHere(std::function<void()> e) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 setEntry(e); start();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 void thread2::startHere(arg_t const& arg, std::function<void()> e) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 setEntry(e); start(arg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 void thread2::setEntry(std::function<void()> e) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 PFC_ASSERT(!isActive());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 m_entryPoint = e;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 void thread2::threadProc() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 m_entryPoint();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 thread::handle_t thread::handleToCurrent() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 return GetCurrentThread();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 return pthread_self();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 thread::arg_t thread::argDefault() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 return arg_t();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 thread::arg_t thread::argCurrentThread() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 arg_t arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 arg.winThreadPriority = GetThreadPriority( GetCurrentThread() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 qos_class_t qos_class = QOS_CLASS_UNSPECIFIED;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 int relative_priority = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 if (pthread_get_qos_class_np(pthread_self(), &qos_class, &relative_priority) == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 arg.appleThreadQOS = (int) qos_class;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 arg.appleRealtivePriority = relative_priority;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 #ifndef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 int policy; sched_param param;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 if (pthread_getschedparam( pthread_self(), &policy, &param) == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 arg.nixSchedPolicy = policy;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 arg.nixSchedParam = param;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 return arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 thread::arg_t thread::argBackground() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 return argWinPriority(THREAD_PRIORITY_LOWEST);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 #elif defined(__APPLE__)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 return argAppleQOS((int)QOS_CLASS_BACKGROUND);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 return argNixPriority(SCHED_OTHER, 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 thread::arg_t thread::argHighPriority() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 return argWinPriority(THREAD_PRIORITY_HIGHEST);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 #elif defined(__ANDROID__)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 // No SCHED_FIFO or SCHED_RR on Android
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 return argNixPriority(SCHED_OTHER, 100);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 return argNixPriority(SCHED_RR, 75);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 thread::arg_t thread::argPlayback() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 // It would be nice to use realtime priority yet lock ourselves to the slow cores, but that just doesn't work
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 // Using priority overrides the request for the slow cores (QOS_CLASS_BACKGROUND)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 // ret.appleThreadQOS = (int) QOS_CLASS_BACKGROUND;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 return argWinPriority(THREAD_PRIORITY_TIME_CRITICAL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 #elif defined(__ANDROID__)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 // No SCHED_FIFO or SCHED_RR on Android
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 return argNixPriority(SCHED_OTHER, 100);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 return argNixPriority(SCHED_FIFO, 100);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 thread::arg_t thread::argUserInitiated() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 return argWinPriority(THREAD_PRIORITY_BELOW_NORMAL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 #elif defined(__APPLE__)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 return argAppleQOS((int) QOS_CLASS_USER_INITIATED);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 return argNixPriority(SCHED_OTHER, 25);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 thread::arg_t thread::argWinPriority(int priority) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 arg_t arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 arg.winThreadPriority = priority;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 return arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 thread::arg_t thread::argAppleQOS(int qos) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 arg_t arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 arg.appleThreadQOS = qos;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 return arg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 #ifndef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 thread::arg_t thread::argNixPriority(int policy, int percent) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 int pval;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 if ( percent <= 0 ) pval = sched_get_priority_min(policy);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 else if ( percent >= 100 ) pval = sched_get_priority_max(policy);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 const int pmin = sched_get_priority_min(policy), pmax = sched_get_priority_max(policy);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 if (pmax > pmin) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 pval = pmin + ((pmax - pmin) * percent / 100);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 pval = pmin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 arg_t ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 ret.nixSchedPolicy = policy;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 ret.nixSchedParam = sched_param { pval };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 void thread::setCurrentPriority(arg_t const& arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 ::SetThreadPriority(GetCurrentThread(), arg.winThreadPriority);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346 #ifdef __APPLE__
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 if (arg.appleThreadQOS != 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 pthread_set_qos_class_self_np((qos_class_t)arg.appleThreadQOS, arg.appleRealtivePriority);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 if (arg.nixSchedPolicy >= 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353 pthread_setschedparam(pthread_self(), arg.nixSchedPolicy, &arg.nixSchedParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358 }