| 594 | static std::map<rdcstr, LogcatThread *> logcatThreads; |
| 595 | |
| 596 | LogcatThread *ProcessLogcat(rdcstr deviceID) |
| 597 | { |
| 598 | LogcatThread *ret = NULL; |
| 599 | |
| 600 | Threading::ThreadHandle joinThread = 0; |
| 601 | |
| 602 | // ensure any previous thread running is really finished |
| 603 | { |
| 604 | SCOPED_LOCK(logcatThreadLock); |
| 605 | |
| 606 | // if this thread is running, kill it immediately |
| 607 | if(logcatThreads[deviceID]) |
| 608 | { |
| 609 | joinThread = logcatThreads[deviceID]->thread; |
| 610 | |
| 611 | { |
| 612 | SCOPED_LOCK(logcatThreads[deviceID]->lock); |
| 613 | logcatThreads[deviceID]->immediateExit = true; |
| 614 | } |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | // if we had a thread to join, do so now. It will remove itself from the above map and |
| 619 | // self-delete, but not detach the thread |
| 620 | if(joinThread) |
| 621 | { |
| 622 | Threading::JoinThread(joinThread); |
| 623 | Threading::CloseThread(joinThread); |
| 624 | } |
| 625 | |
| 626 | // start a new thread to monitor this device's logcat |
| 627 | ret = new LogcatThread; |
| 628 | |
| 629 | { |
| 630 | SCOPED_LOCK(logcatThreadLock); |
| 631 | logcatThreads[deviceID] = ret; |
| 632 | } |
| 633 | |
| 634 | ret->deviceID = deviceID; |
| 635 | ret->thread = Threading::CreateThread([ret]() { |
| 636 | bool done = false; |
| 637 | |
| 638 | RDCDEBUG("Starting monitoring logcat on %s", ret->deviceID.c_str()); |
| 639 | |
| 640 | while(!done) |
| 641 | { |
| 642 | // tick the logcat |
| 643 | ret->Tick(); |
| 644 | |
| 645 | // sleep 400ms, but in small chunks to let us respond to immediateExit more quickly |
| 646 | for(int i = 0; i < 10; i++) |
| 647 | { |
| 648 | Threading::Sleep(40); |
| 649 | |
| 650 | time_t now = Timing::GetUTCTime(); |
| 651 | { |
| 652 | SCOPED_LOCK(ret->lock); |
| 653 | if(ret->immediateExit || (ret->finishTime && ret->finishTime + 5 < now)) |
no test coverage detected