History

use pthread_condition instead of semaphores on apple platform

Karina committed 10 years ago

Commit c12b88a1 parent 30328b810 files · +108 −146Browse files

Showing the changes to codec/common/src/WelsThreadLib.cpp (1 of 10 files). Show all

Unified · Split

codec/common/src/WelsThreadLib.cpp+79−102
@@ -133,11 +133,10 @@ WELS_THREAD_ERROR_CODE WelsMutexDestroy (WELS_MUTEX* mutex) { · 132 unmodified lines
133 133
134WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* event, const char* event_name) {134WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* event, const char* event_name) {
135 WELS_EVENT h = CreateEvent (NULL, FALSE, FALSE, NULL);135 WELS_EVENT h = CreateEvent (NULL, FALSE, FALSE, NULL);
136 136 *event = h;
137 if (h == NULL) {137 if (h == NULL) {
138 return WELS_THREAD_ERROR_GENERAL;138 return WELS_THREAD_ERROR_GENERAL;
139 }139 }
140 *event = h;
141 return WELS_THREAD_ERROR_OK;140 return WELS_THREAD_ERROR_OK;
142}141}
143 142
@@ -148,26 +147,20 @@ WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) { · 4 unmodified lines
148 return WELS_THREAD_ERROR_GENERAL;147 return WELS_THREAD_ERROR_GENERAL;
149}148}
150 149
151WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {150WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
152 return WaitForSingleObject (*event, INFINITE);151 return WaitForSingleObject (*event, INFINITE);
153}152}
154 153
155WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {154WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
156 return WaitForSingleObject (*event, dwMilliseconds);155 return WaitForSingleObject (*event, dwMilliseconds);
157}156}
158 157
159WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,158WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
160 WELS_EVENT* event_list, WELS_EVENT* master_event) {159 WELS_EVENT* event_list, WELS_EVENT* master_even, WELS_MUTEX* pMutext) {
161 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects160 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
162 return WaitForMultipleObjects (nCount, event_list, FALSE, INFINITE);161 return WaitForMultipleObjects (nCount, event_list, FALSE, INFINITE);
163}162}
164 163
165WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
166 WELS_EVENT* event_list, WELS_EVENT* master_event) {
167 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
168 return WaitForMultipleObjects (nCount, event_list, TRUE, INFINITE);
169}
170
171WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {164WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
172 CloseHandle (*event);165 CloseHandle (*event);
173 166
@@ -278,10 +271,10 @@ WELS_THREAD_ERROR_CODE WelsThreadCreate (WELS_THREAD_HANDLE* thread, LPWELS_ · 104 unmodified lines
278 271
279WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) {272WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) {
280#ifdef APPLE_IOS273#ifdef APPLE_IOS
281 pthread_setname_np(thread_name);274 pthread_setname_np (thread_name);
282#endif275#endif
283#if defined(__ANDROID__) && __ANDROID_API__ >= 9276#if defined(__ANDROID__) && __ANDROID_API__ >= 9
284 pthread_setname_np(pthread_self(), thread_name);277 pthread_setname_np (pthread_self(), thread_name);
285#endif278#endif
286 // do nothing279 // do nothing
287 return WELS_THREAD_ERROR_OK;280 return WELS_THREAD_ERROR_OK;
@@ -299,46 +292,33 @@ WELS_THREAD_HANDLE WelsThreadSelf() { · 11 unmodified lines
299 292
300WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {293WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {
301#ifdef __APPLE__294#ifdef __APPLE__
302 if (p_event == NULL) {295 WELS_THREAD_ERROR_CODE err= pthread_cond_init (p_event, NULL);
303 return WELS_THREAD_ERROR_GENERAL;296 return err;
304 }
305 char strSuffix[100] = { 0 };
306 if (NULL == event_name) {
307 sprintf (strSuffix, "WelsSem%ld_p%ld", (intptr_t)p_event, (long) (getpid()));
308 event_name = &strSuffix[0];
309 }
310 *p_event = sem_open (event_name, O_CREAT, (S_IRUSR | S_IWUSR)/*0600*/, 0);
311 if (*p_event == (sem_t*)SEM_FAILED) {
312 sem_unlink (event_name);
313 *p_event = NULL;
314 return WELS_THREAD_ERROR_GENERAL;
315 } else {
316 //printf("event_open:%x, %s\n", p_event, event_name);
317 return WELS_THREAD_ERROR_OK;
318 }
319#else297#else
320 WELS_EVENT event = (WELS_EVENT) malloc (sizeof (*event));298 WELS_EVENT event = (WELS_EVENT) malloc (sizeof (*event));
321 if (event == NULL)299 if (event == NULL){
300 *p_event = NULL;
322 return WELS_THREAD_ERROR_GENERAL;301 return WELS_THREAD_ERROR_GENERAL;
302 }
323 WELS_THREAD_ERROR_CODE err = sem_init (event, 0, 0);303 WELS_THREAD_ERROR_CODE err = sem_init (event, 0, 0);
324 if (!err) {304 if (!err) {
325 *p_event = event;305 *p_event = event;
326 return err;306 return err;
327 }307 }
328 free (event);308 free (event);
309 *p_event = NULL;
329 return err;310 return err;
330#endif311#endif
331}312}
332WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {313WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
333 //printf("event_close:%x, %s\n", event, event_name);314 //printf("event_close:%x, %s\n", event, event_name);
334#ifdef __APPLE__315#ifdef __APPLE__
335 WELS_THREAD_ERROR_CODE err = sem_close (*event); // match with sem_open316 WELS_THREAD_ERROR_CODE err = pthread_cond_destroy (event);
336 if (event_name)
337 sem_unlink (event_name);
338 return err;317 return err;
339#else318#else
340 WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init319 WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init
341 free (*event);320 free (*event);
321 *event = NULL;
342 return err;322 return err;
343#endif323#endif
344}324}
@@ -349,37 +329,37 @@ void WelsSleep (uint32_t dwMilliSecond) { · 4 unmodified lines
349 329
350WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {330WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {
351 WELS_THREAD_ERROR_CODE err = 0;331 WELS_THREAD_ERROR_CODE err = 0;
332#ifdef __APPLE__
333 err = pthread_cond_signal (event);
334#else
352// int32_t val = 0;335// int32_t val = 0;
353// sem_getvalue(event, &val);336// sem_getvalue(event, &val);
354// fprintf( stderr, "before signal it, val= %d..\n",val );337// fprintf( stderr, "before signal it, val= %d..\n",val );
355 err = sem_post (*event);338 if (event != NULL)
339 err = sem_post (*event);
356// sem_getvalue(event, &val);340// sem_getvalue(event, &val);
357// fprintf( stderr, "after signal it, val= %d..\n",val );341// fprintf( stderr, "after signal it, val= %d..\n",val );
342#endif
358 return err;343 return err;
359}344}
360 345
361WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {346WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
347#ifdef __APPLE__
348 return pthread_cond_wait (event, pMutex);
349#else
362 return sem_wait (*event); // blocking until signaled350 return sem_wait (*event); // blocking until signaled
351#endif
363}352}
364 353
365WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {354WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
355
366 if (dwMilliseconds != (uint32_t) - 1) {356 if (dwMilliseconds != (uint32_t) - 1) {
367 return sem_wait (*event);
368 } else {
369#if defined(__APPLE__)357#if defined(__APPLE__)
370 int32_t err = 0;358 return pthread_cond_wait (event, pMutex);
371 int32_t wait_count = 0;
372 do {
373 err = sem_trywait (*event);
374 if (WELS_THREAD_ERROR_OK == err)
375 break;// WELS_THREAD_ERROR_OK;
376 else if (wait_count > 0)
377 break;
378 usleep (dwMilliseconds * 1000);
379 ++ wait_count;
380 } while (1);
381 return err;
382#else359#else
360 return sem_wait (*event);
361#endif
362 } else {
383 struct timespec ts;363 struct timespec ts;
384 struct timeval tv;364 struct timeval tv;
385 365
@@ -389,26 +369,30 @@ WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t · 3 unmodified lines
389 ts.tv_sec = tv.tv_sec + ts.tv_nsec / 1000000000;369 ts.tv_sec = tv.tv_sec + ts.tv_nsec / 1000000000;
390 ts.tv_nsec %= 1000000000;370 ts.tv_nsec %= 1000000000;
391 371
372#if defined(__APPLE__)
373 return pthread_cond_timedwait (event, pMutex, &ts);
374#else
392 return sem_timedwait (*event, &ts);375 return sem_timedwait (*event, &ts);
393#endif//__APPLE__376#endif
394 }377 }
378
395}379}
396 380
397WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,381WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
398 WELS_EVENT* event_list, WELS_EVENT* master_event) {382 WELS_EVENT* event_list, WELS_EVENT* master_event, WELS_MUTEX* pMutex) {
399 uint32_t nIdx = 0;383 uint32_t nIdx = 0;
400 uint32_t uiAccessTime = 2; // 2 us once384 uint32_t uiAccessTime = 2; // 2 us once
401 385
402 if (nCount == 0)386 if (nCount == 0)
403 return WELS_THREAD_ERROR_WAIT_FAILED;387 return WELS_THREAD_ERROR_WAIT_FAILED;
404 388#if defined(__APPLE__)
405 if (master_event != NULL) {389 if (master_event != NULL) {
406 // This design relies on the events actually being semaphores;390 // This design relies on the events actually being semaphores;
407 // if multiple events in the list have been signalled, the master391 // if multiple events in the list have been signalled, the master
408 // event should have a similar count (events in windows can't keep392 // event should have a similar count (events in windows can't keep
409 // track of the actual count, but the master event isn't needed there393 // track of the actual count, but the master event isn't needed there
410 // since it uses WaitForMultipleObjects).394 // since it uses WaitForMultipleObjects).
411 int32_t err = sem_wait (*master_event);395 int32_t err = pthread_cond_wait (master_event, pMutex);
412 if (err != WELS_THREAD_ERROR_OK)396 if (err != WELS_THREAD_ERROR_OK)
413 return err;397 return err;
414 uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled398 uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
@@ -425,7 +409,7 @@ WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, · 10 unmodified lines
425 * pthread_cond_timedwait() might be better choice if need409 * pthread_cond_timedwait() might be better choice if need
426 */410 */
427 do {411 do {
428 err = sem_trywait (event_list[nIdx]);412 err = pthread_cond_wait (&event_list[nIdx], pMutex);
429 if (WELS_THREAD_ERROR_OK == err)413 if (WELS_THREAD_ERROR_OK == err)
430 return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;414 return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
431 else if (wait_count > 0 || uiAccessTime == 0)415 else if (wait_count > 0 || uiAccessTime == 0)
@@ -446,60 +430,53 @@ WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, · 14 unmodified lines
446 uiAccessTime = 2;430 uiAccessTime = 2;
447 }431 }
448 }432 }
449 433#else
450 return WELS_THREAD_ERROR_WAIT_FAILED;434 if (master_event != NULL) {
451}435 // This design relies on the events actually being semaphores;
452 436 // if multiple events in the list have been signalled, the master
453WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitAllBlocking (uint32_t nCount,437 // event should have a similar count (events in windows can't keep
454 WELS_EVENT* event_list, WELS_EVENT* master_event) {438 // track of the actual count, but the master event isn't needed there
455 uint32_t nIdx = 0;439 // since it uses WaitForMultipleObjects).
456 uint32_t uiCountSignals = 0;440 int32_t err = sem_wait (*master_event);
457 uint32_t uiSignalFlag = 0; // UGLY: suppose maximal event number up to 32441 if (err != WELS_THREAD_ERROR_OK)
458 442 return err;
459 if (nCount == 0 || nCount > (sizeof (uint32_t) << 3))443 uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
460 return WELS_THREAD_ERROR_WAIT_FAILED;444 }
461 445
462 while (1) {446 while (1) {
463 nIdx = 0; // access each event by order447 nIdx = 0; // access each event by order
464 while (nIdx < nCount) {448 while (nIdx < nCount) {
465 const uint32_t kuiBitwiseFlag = (1 << nIdx);449 int32_t err = 0;
466 450 int32_t wait_count = 0;
467 if ((uiSignalFlag & kuiBitwiseFlag) != kuiBitwiseFlag) { // non-blocking mode451
468 int32_t err = 0;452 /*
469// fprintf( stderr, "sem_wait(): start to wait event %d..\n", nIdx );453 * although such interface is not used in __GNUC__ like platform, to use
470 if (master_event == NULL) {454 * pthread_cond_timedwait() might be better choice if need
471 err = sem_wait (event_list[nIdx]);455 */
472 } else {456 do {
473 err = sem_wait (*master_event);457 err = sem_trywait (event_list[nIdx]);
474 if (err == WELS_THREAD_ERROR_OK) {458 if (WELS_THREAD_ERROR_OK == err)
475 err = sem_wait (event_list[nIdx]);459 return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
476 if (err != WELS_THREAD_ERROR_OK) {460 else if (wait_count > 0 || uiAccessTime == 0)
477 // We successfully waited for the master event,461 break;
478 // but waiting for the individual event failed (e.g. EINTR?).462 usleep (uiAccessTime);
479 // Increase the master event count so that the next retry will463 ++ wait_count;
480 // work as intended.464 } while (1);
481 sem_post (*master_event);
482 }
483 }
484 }
485// fprintf( stderr, "sem_wait(): wait event %d result %d errno %d..\n", nIdx, err, errno );
486 if (WELS_THREAD_ERROR_OK == err) {
487// int32_t val = 0;
488// sem_getvalue(&event_list[nIdx], &val);
489// fprintf( stderr, "after sem_timedwait(), event_list[%d] semaphore value= %d..\n", nIdx, val);
490
491 uiSignalFlag |= kuiBitwiseFlag;
492 ++ uiCountSignals;
493 if (uiCountSignals >= nCount) {
494 return WELS_THREAD_ERROR_OK;
495 }
496 }
497 }
498 // we do need access next event next time465 // we do need access next event next time
499 ++ nIdx;466 ++ nIdx;
500 }467 }
468 usleep (1); // switch to working threads
469 if (master_event != NULL) {
470 // A master event was used and was signalled, but none of the events in the
471 // list was found to be signalled, thus wait a little more when rechecking
472 // the list to avoid busylooping here.
473 // If we ever hit this codepath it's mostly a bug in the code that signals
474 // the events.
475 uiAccessTime = 2;
476 }
501 }477 }
502 478
479#endif
503 return WELS_THREAD_ERROR_WAIT_FAILED;480 return WELS_THREAD_ERROR_WAIT_FAILED;
504}481}
505 482
@@ -519,7 +496,7 @@ WELS_THREAD_ERROR_CODE WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* p · 13 unmodified lines
519#else496#else
520 int32_t count = 0;497 int32_t count = 0;
521 for (int i = 0; i < CPU_SETSIZE; i++) {498 for (int i = 0; i < CPU_SETSIZE; i++) {
522 if (CPU_ISSET(i, &cpuset)) {499 if (CPU_ISSET (i, &cpuset)) {
523 count++;500 count++;
524 }501 }
525 }502 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t