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
133133
134134 WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* event, const char* event_name) {
135135 WELS_EVENT h = CreateEvent (NULL, FALSE, FALSE, NULL);
136−
136+ *event = h;
137137 if (h == NULL) {
138138 return WELS_THREAD_ERROR_GENERAL;
139139 }
140− *event = h;
141140 return WELS_THREAD_ERROR_OK;
142141 }
143142
@@ -148,26 +147,20 @@ WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) { · 4 unmodified lines
148147 return WELS_THREAD_ERROR_GENERAL;
149148 }
150149
151−WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
150+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
152151 return WaitForSingleObject (*event, INFINITE);
153152 }
154153
155−WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
154+WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
156155 return WaitForSingleObject (*event, dwMilliseconds);
157156 }
158157
159158 WELS_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) {
161160 // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
162161 return WaitForMultipleObjects (nCount, event_list, FALSE, INFINITE);
163162 }
164163
165−WELS_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−
171164 WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
172165 CloseHandle (*event);
173166
@@ -278,10 +271,10 @@ WELS_THREAD_ERROR_CODE WelsThreadCreate (WELS_THREAD_HANDLE* thread, LPWELS_ · 104 unmodified lines
278271
279272 WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) {
280273 #ifdef APPLE_IOS
281− pthread_setname_np(thread_name);
274+ pthread_setname_np (thread_name);
282275 #endif
283276 #if defined(__ANDROID__) && __ANDROID_API__ >= 9
284− pthread_setname_np(pthread_self(), thread_name);
277+ pthread_setname_np (pthread_self(), thread_name);
285278 #endif
286279 // do nothing
287280 return WELS_THREAD_ERROR_OK;
@@ -299,46 +292,33 @@ WELS_THREAD_HANDLE WelsThreadSelf() { · 11 unmodified lines
299292
300293 WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {
301294 #ifdef __APPLE__
302− if (p_event == NULL) {
303− return WELS_THREAD_ERROR_GENERAL;
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− }
295+ WELS_THREAD_ERROR_CODE err= pthread_cond_init (p_event, NULL);
296+ return err;
319297 #else
320298 WELS_EVENT event = (WELS_EVENT) malloc (sizeof (*event));
321− if (event == NULL)
299+ if (event == NULL){
300+ *p_event = NULL;
322301 return WELS_THREAD_ERROR_GENERAL;
302+ }
323303 WELS_THREAD_ERROR_CODE err = sem_init (event, 0, 0);
324304 if (!err) {
325305 *p_event = event;
326306 return err;
327307 }
328308 free (event);
309+ *p_event = NULL;
329310 return err;
330311 #endif
331312 }
332313 WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
333314 //printf("event_close:%x, %s\n", event, event_name);
334315 #ifdef __APPLE__
335− WELS_THREAD_ERROR_CODE err = sem_close (*event); // match with sem_open
336− if (event_name)
337− sem_unlink (event_name);
316+ WELS_THREAD_ERROR_CODE err = pthread_cond_destroy (event);
338317 return err;
339318 #else
340319 WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init
341320 free (*event);
321+ *event = NULL;
342322 return err;
343323 #endif
344324 }
@@ -349,37 +329,37 @@ void WelsSleep (uint32_t dwMilliSecond) { · 4 unmodified lines
349329
350330 WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {
351331 WELS_THREAD_ERROR_CODE err = 0;
332+#ifdef __APPLE__
333+ err = pthread_cond_signal (event);
334+#else
352335 // int32_t val = 0;
353336 // sem_getvalue(event, &val);
354337 // fprintf( stderr, "before signal it, val= %d..\n",val );
355− err = sem_post (*event);
338+ if (event != NULL)
339+ err = sem_post (*event);
356340 // sem_getvalue(event, &val);
357341 // fprintf( stderr, "after signal it, val= %d..\n",val );
342+#endif
358343 return err;
359344 }
360345
361−WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
346+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
347+#ifdef __APPLE__
348+ return pthread_cond_wait (event, pMutex);
349+#else
362350 return sem_wait (*event); // blocking until signaled
351+#endif
363352 }
364353
365−WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
354+WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
355+
366356 if (dwMilliseconds != (uint32_t) - 1) {
367− return sem_wait (*event);
368− } else {
369357 #if defined(__APPLE__)
370− int32_t err = 0;
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;
358+ return pthread_cond_wait (event, pMutex);
382359 #else
360+ return sem_wait (*event);
361+#endif
362+ } else {
383363 struct timespec ts;
384364 struct timeval tv;
385365
@@ -389,26 +369,30 @@ WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t · 3 unmodified lines
389369 ts.tv_sec = tv.tv_sec + ts.tv_nsec / 1000000000;
390370 ts.tv_nsec %= 1000000000;
391371
372+#if defined(__APPLE__)
373+ return pthread_cond_timedwait (event, pMutex, &ts);
374+#else
392375 return sem_timedwait (*event, &ts);
393−#endif//__APPLE__
376+#endif
394377 }
378+
395379 }
396380
397381 WELS_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) {
399383 uint32_t nIdx = 0;
400384 uint32_t uiAccessTime = 2; // 2 us once
401385
402386 if (nCount == 0)
403387 return WELS_THREAD_ERROR_WAIT_FAILED;
404−
388+#if defined(__APPLE__)
405389 if (master_event != NULL) {
406390 // This design relies on the events actually being semaphores;
407391 // if multiple events in the list have been signalled, the master
408392 // event should have a similar count (events in windows can't keep
409393 // track of the actual count, but the master event isn't needed there
410394 // since it uses WaitForMultipleObjects).
411− int32_t err = sem_wait (*master_event);
395+ int32_t err = pthread_cond_wait (master_event, pMutex);
412396 if (err != WELS_THREAD_ERROR_OK)
413397 return err;
414398 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
425409 * pthread_cond_timedwait() might be better choice if need
426410 */
427411 do {
428− err = sem_trywait (event_list[nIdx]);
412+ err = pthread_cond_wait (&event_list[nIdx], pMutex);
429413 if (WELS_THREAD_ERROR_OK == err)
430414 return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
431415 else if (wait_count > 0 || uiAccessTime == 0)
@@ -446,60 +430,53 @@ WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, · 14 unmodified lines
446430 uiAccessTime = 2;
447431 }
448432 }
449−
450− return WELS_THREAD_ERROR_WAIT_FAILED;
451−}
452−
453−WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
454− WELS_EVENT* event_list, WELS_EVENT* master_event) {
455− uint32_t nIdx = 0;
456− uint32_t uiCountSignals = 0;
457− uint32_t uiSignalFlag = 0; // UGLY: suppose maximal event number up to 32
458−
459− if (nCount == 0 || nCount > (sizeof (uint32_t) << 3))
460− return WELS_THREAD_ERROR_WAIT_FAILED;
433+#else
434+ if (master_event != NULL) {
435+ // This design relies on the events actually being semaphores;
436+ // if multiple events in the list have been signalled, the master
437+ // event should have a similar count (events in windows can't keep
438+ // track of the actual count, but the master event isn't needed there
439+ // since it uses WaitForMultipleObjects).
440+ int32_t err = sem_wait (*master_event);
441+ if (err != WELS_THREAD_ERROR_OK)
442+ return err;
443+ uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
444+ }
461445
462446 while (1) {
463447 nIdx = 0; // access each event by order
464448 while (nIdx < nCount) {
465− const uint32_t kuiBitwiseFlag = (1 << nIdx);
466−
467− if ((uiSignalFlag & kuiBitwiseFlag) != kuiBitwiseFlag) { // non-blocking mode
468− int32_t err = 0;
469−// fprintf( stderr, "sem_wait(): start to wait event %d..\n", nIdx );
470− if (master_event == NULL) {
471− err = sem_wait (event_list[nIdx]);
472− } else {
473− err = sem_wait (*master_event);
474− if (err == WELS_THREAD_ERROR_OK) {
475− err = sem_wait (event_list[nIdx]);
476− if (err != WELS_THREAD_ERROR_OK) {
477− // We successfully waited for the master event,
478− // but waiting for the individual event failed (e.g. EINTR?).
479− // Increase the master event count so that the next retry will
480− // work as intended.
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− }
449+ int32_t err = 0;
450+ int32_t wait_count = 0;
451+
452+ /*
453+ * although such interface is not used in __GNUC__ like platform, to use
454+ * pthread_cond_timedwait() might be better choice if need
455+ */
456+ do {
457+ err = sem_trywait (event_list[nIdx]);
458+ if (WELS_THREAD_ERROR_OK == err)
459+ return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
460+ else if (wait_count > 0 || uiAccessTime == 0)
461+ break;
462+ usleep (uiAccessTime);
463+ ++ wait_count;
464+ } while (1);
498465 // we do need access next event next time
499466 ++ nIdx;
500467 }
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+ }
501477 }
502478
479+#endif
503480 return WELS_THREAD_ERROR_WAIT_FAILED;
504481 }
505482
@@ -519,7 +496,7 @@ WELS_THREAD_ERROR_CODE WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* p · 13 unmodified lines
519496 #else
520497 int32_t count = 0;
521498 for (int i = 0; i < CPU_SETSIZE; i++) {
522− if (CPU_ISSET(i, &cpuset)) {
499+ if (CPU_ISSET (i, &cpuset)) {
523500 count++;
524501 }
525502 }

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