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