foobar2000 SDK  2015-01-14
threads.cpp
Go to the documentation of this file.
1 #include "pfc.h"
2 
3 #ifdef __APPLE__
4 #include <sys/sysctl.h>
5 #include <sys/stat.h>
6 #endif
7 
8 #ifndef _WINDOWS
9 #ifdef __ANDROID__
10 #include "cpu-features.h"
11 #else
12 #include <thread>
13 #endif
14 #endif
15 
16 namespace pfc {
18 #ifdef _WINDOWS
19  DWORD_PTR mask,system;
20  t_size ret = 0;
21  GetProcessAffinityMask(GetCurrentProcess(),&mask,&system);
22  for(t_size n=0;n<sizeof(mask)*8;n++) {
23  if (mask & ((DWORD_PTR)1<<n)) ret++;
24  }
25  if (ret == 0) return 1;
26  return ret;
27 #elif defined(__ANDROID__)
28  return android_getCpuCount();
29 #else
30  return std::thread::hardware_concurrency();
31 #endif
32 
33 
34 #if 0 // OSX
35  size_t len;
36  unsigned int ncpu;
37 
38  len = sizeof(ncpu);
39  sysctlbyname ("hw.ncpu",&ncpu,&len,NULL,0);
40 
41  return ncpu;
42 #endif
43  }
44 
46  if (taskCountLimit <= 1) return 1;
47  return pfc::min_t(taskCountLimit,getOptimalWorkerThreadCount());
48  }
49 
50 
51  void thread::entry() {
52  try {
53  threadProc();
54  } catch(...) {}
55  }
56 
57 #ifdef _WINDOWS
58  thread::thread() : m_thread(INVALID_HANDLE_VALUE)
59  {
60  }
61 
62  void thread::close() {
63  if (isActive()) {
64 
65  int ctxPriority = GetThreadPriority( GetCurrentThread() );
66  if (ctxPriority > GetThreadPriority( m_thread ) ) SetThreadPriority( m_thread, ctxPriority );
67 
68  if (WaitForSingleObject(m_thread,INFINITE) != WAIT_OBJECT_0) crash();
69  CloseHandle(m_thread); m_thread = INVALID_HANDLE_VALUE;
70  }
71  }
72  bool thread::isActive() const {
73  return m_thread != INVALID_HANDLE_VALUE;
74  }
75  void thread::winStart(int priority, DWORD * outThreadID) {
76  close();
77  HANDLE thread;
78  thread = (HANDLE)_beginthreadex(NULL, 0, g_entry, reinterpret_cast<void*>(this), CREATE_SUSPENDED, (unsigned int*)outThreadID);
79  if (thread == NULL) throw exception_creation();
80  SetThreadPriority(thread, priority);
81  ResumeThread(thread);
82  m_thread = thread;
83  }
84  void thread::startWithPriority(int priority) {
85  winStart(priority, NULL);
86  }
87  void thread::setPriority(int priority) {
88  PFC_ASSERT(isActive());
89  SetThreadPriority(m_thread, priority);
90  }
91  void thread::start() {
92  startWithPriority(GetThreadPriority(GetCurrentThread()));
93  }
94 
95  unsigned CALLBACK thread::g_entry(void* p_instance) {
96  reinterpret_cast<thread*>(p_instance)->entry(); return 0;
97  }
98 
100  PFC_ASSERT(isActive());
101  return GetThreadPriority( m_thread );
102  }
103 
105  return GetThreadPriority( GetCurrentThread() );
106  }
107 #else
108  thread::thread() : m_thread(), m_threadValid() {
109  }
110 
111 #ifndef __APPLE__ // Apple specific entrypoint in obj-c.mm
112  void * thread::g_entry( void * arg ) {
113  reinterpret_cast<thread*>( arg )->entry();
114  return NULL;
115  }
116 #endif
117 
118  void thread::startWithPriority(int priority) {
119  close();
120 #ifdef __APPLE__
122 #endif
123  pthread_t thread;
124  pthread_attr_t attr;
125  pthread_attr_init(&attr);
126 
127  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
128 
129  if (pthread_create(&thread, &attr, g_entry, reinterpret_cast<void*>(this)) < 0) throw exception_creation();
130 
131  pthread_attr_destroy(&attr);
132  m_threadValid = true;
133  m_thread = thread;
134  }
135 
136  void thread::setPriority(int priority) {
137  PFC_ASSERT(isActive());
138  // not avail
139  }
140  int thread::getPriority() {
141  return 0; // not avail
142  }
144  return 0; // not avail
145  }
146 
147  void thread::start() {
149  }
150 
151  void thread::close() {
152  if (m_threadValid) {
153  void * rv = NULL;
154  pthread_join( m_thread, & rv ); m_thread = 0;
155  m_threadValid = false;
156  }
157  }
158 
159  bool thread::isActive() const {
160  return m_threadValid;
161  }
162 #endif
163 }
T min_t(const T &item1, const T &item2)
Definition: primitives.h:556
void start()
Definition: threads.cpp:91
t_size getOptimalWorkerThreadCountEx(t_size taskCountLimit)
Definition: threads.cpp:45
void startWithPriority(int priority)
Definition: threads.cpp:84
void close()
Definition: threads.cpp:62
t_size getOptimalWorkerThreadCount()
Definition: threads.cpp:17
bool isActive() const
Definition: threads.cpp:72
typedef HANDLE(WINAPI *pPowerCreateRequest_t)(__in void *Context)
IMPORTANT: all classes derived from thread must call waitTillDone() in their destructor, to avoid object destruction during a virtual function call!
Definition: threads.h:11
size_t t_size
Definition: int_types.h:48
void crash()
Definition: other.cpp:105
void setPriority(int priority)
Definition: threads.cpp:87
virtual void threadProc()
Definition: threads.h:28
HANDLE m_thread
Definition: threads.h:39
int getPriority()
Definition: threads.cpp:99
static unsigned CALLBACK g_entry(void *p_instance)
Definition: obj-c.mm:22
bool m_threadValid
Definition: threads.h:42
static int currentPriority()
Definition: threads.cpp:104
int android_getCpuCount(void)
Definition: cpu-features.c:935
static void appleStartThreadPrologue()
Definition: obj-c.mm:28
void winStart(int priority, DWORD *outThreadID)
Definition: threads.cpp:75
void entry()
Definition: threads.cpp:51