Showing the changes to codec/common/src/WelsThreadLib.cpp (1 of 10 files). Show all
Unified · Split
| @@ -133,11 +133,10 @@ WELS_THREAD_ERROR_CODE WelsMutexDestroy (WELS_MUTEX* mutex) { · 132 unmodified lines | |||
| 133 | 133 | ||
| 134 | WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* event, const char* event_name) { | 134 | WELS_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 | ||
| 151 | WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) { | 150 | WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) { |
| 152 | return WaitForSingleObject (*event, INFINITE); | 151 | return WaitForSingleObject (*event, INFINITE); |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 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) { |
| 156 | return WaitForSingleObject (*event, dwMilliseconds); | 155 | return WaitForSingleObject (*event, dwMilliseconds); |
| 157 | } | 156 | } |
| 158 | 157 | ||
| 159 | WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, | 158 | 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) { |
| 161 | // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects | 160 | // 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 | ||
| 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 | |||
| 171 | WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) { | 164 | WELS_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 | ||
| 279 | WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) { | 272 | WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) { |
| 280 | #ifdef APPLE_IOS | 273 | #ifdef APPLE_IOS |
| 281 | pthread_setname_np(thread_name); | 274 | pthread_setname_np (thread_name); |
| 282 | #endif | 275 | #endif |
| 283 | #if defined(__ANDROID__) && __ANDROID_API__ >= 9 | 276 | #if defined(__ANDROID__) && __ANDROID_API__ >= 9 |
| 284 | pthread_setname_np(pthread_self(), thread_name); | 277 | pthread_setname_np (pthread_self(), thread_name); |
| 285 | #endif | 278 | #endif |
| 286 | // do nothing | 279 | // 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 | ||
| 300 | WELS_THREAD_ERROR_CODE WelsEventOpen (WELS_EVENT* p_event, const char* event_name) { | 293 | WELS_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 | #else | 297 | #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 | #endif | 311 | #endif |
| 331 | } | 312 | } |
| 332 | WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) { | 313 | WELS_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_open | 316 | 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 | #else | 318 | #else |
| 340 | WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init | 319 | 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 | #endif | 323 | #endif |
| 344 | } | 324 | } |
| @@ -349,37 +329,37 @@ void WelsSleep (uint32_t dwMilliSecond) { · 4 unmodified lines | |||
| 349 | 329 | ||
| 350 | WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) { | 330 | WELS_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 | ||
| 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 | ||
| 362 | return sem_wait (*event); // blocking until signaled | 350 | return sem_wait (*event); // blocking until signaled |
| 351 | #endif | ||
| 363 | } | 352 | } |
| 364 | 353 | ||
| 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 | |||
| 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 | #else | 359 | #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 | ||
| 397 | WELS_THREAD_ERROR_CODE WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, | 381 | 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) { |
| 399 | uint32_t nIdx = 0; | 383 | uint32_t nIdx = 0; |
| 400 | uint32_t uiAccessTime = 2; // 2 us once | 384 | 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 master | 391 | // if multiple events in the list have been signalled, the master |
| 408 | // event should have a similar count (events in windows can't keep | 392 | // 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 there | 393 | // 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 signalled | 398 | 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 need | 409 | * 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 | |
| 453 | WELS_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 32 | 441 | 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 order | 447 | 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 mode | 451 | |
| 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 will | 463 | ++ 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 time | 465 | // 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 | #else | 496 | #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 | } |