|
1
|
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 }
|