@@ -523,20 +523,21 @@ DefaultSocketProvider::~DefaultSocketProvider()
523523
524524void DefaultSocketProvider::start ()
525525{
526- std::unique_lock<std::mutex> lock (m_mutex);
526+ util::CheckedUniqueLock lock (m_mutex);
527527 // Has the thread already been started or is running
528528 if (m_state == State::Starting || m_state == State::Running)
529529 return ; // early return
530530
531531 // If the thread has been previously run, make sure it has been joined first
532- if (m_state == State::Stopping ) {
532+ if (m_thread. joinable () ) {
533533 state_wait_for (lock, State::Stopped);
534+ m_thread.join ();
534535 }
535536
536537 m_logger_ptr->trace (" Default event loop: start()" );
537538 REALM_ASSERT (m_state == State::Stopped);
538539
539- do_state_update (lock, State::Starting);
540+ do_state_update (State::Starting);
540541 m_thread = std::thread{&DefaultSocketProvider::event_loop, this };
541542 // Wait for the thread to start before continuing
542543 state_wait_for (lock, State::Running);
@@ -545,17 +546,17 @@ void DefaultSocketProvider::start()
545546void DefaultSocketProvider::OnlyForTesting::run_event_loop_on_current_thread (DefaultSocketProvider* provider)
546547{
547548 {
548- std::unique_lock<std::mutex> lk (provider->m_mutex );
549+ util::CheckedLockGuard lk (provider->m_mutex );
549550 REALM_ASSERT (provider->m_state == State::Stopped);
550- provider->do_state_update (lk, State::Starting);
551+ provider->do_state_update (State::Starting);
551552 }
552553
553554 provider->event_loop ();
554555}
555556
556557void DefaultSocketProvider::OnlyForTesting::prep_event_loop_for_restart (DefaultSocketProvider* provider)
557558{
558- std::unique_lock<std::mutex> lk (provider->m_mutex );
559+ util::CheckedLockGuard lk (provider->m_mutex );
559560 REALM_ASSERT (provider->m_state == State::Stopped);
560561 provider->m_service .reset ();
561562}
@@ -569,21 +570,22 @@ void DefaultSocketProvider::event_loop()
569570 if (m_observer_ptr)
570571 m_observer_ptr->will_destroy_thread ();
571572
572- std::unique_lock<std::mutex> lock (m_mutex);
573- // Did we get here due to an unhandled exception?
574- if (m_state != State::Stopping) {
575- m_logger_ptr->error (" Default event loop: thread exited unexpectedly" );
573+ {
574+ util::CheckedLockGuard lock (m_mutex);
575+ // Did we get here due to an unhandled exception?
576+ if (m_state != State::Stopping) {
577+ m_logger_ptr->error (" Default event loop: thread exited unexpectedly" );
578+ }
579+ m_state = State::Stopped;
576580 }
577- m_state = State::Stopped;
578- lock.unlock ();
579581 m_state_cv.notify_all ();
580582 });
581583
582584 if (m_observer_ptr)
583585 m_observer_ptr->did_create_thread ();
584586
585587 {
586- std::lock_guard<std::mutex> lock (m_mutex);
588+ util::CheckedLockGuard lock (m_mutex);
587589 REALM_ASSERT (m_state == State::Starting);
588590 }
589591
@@ -596,7 +598,7 @@ void DefaultSocketProvider::event_loop()
596598
597599 REALM_ASSERT (status.is_ok ());
598600
599- std::unique_lock<std::mutex> lock (m_mutex);
601+ util::CheckedLockGuard lock (m_mutex);
600602 // This is a callback from a previous generation
601603 if (m_event_loop_generation != my_generation) {
602604 return ;
@@ -606,7 +608,7 @@ void DefaultSocketProvider::event_loop()
606608 }
607609 m_logger_ptr->trace (" Default event loop: service run" );
608610 REALM_ASSERT (m_state == State::Starting);
609- do_state_update (lock, State::Running);
611+ do_state_update (State::Running);
610612 });
611613
612614 // If there is no event loop observer or handle_error function registered, then just
@@ -619,11 +621,12 @@ void DefaultSocketProvider::event_loop()
619621 m_service.run_until_stopped (); // Throws
620622 }
621623 catch (const std::exception& e) {
622- REALM_ASSERT (m_observer_ptr); // should not change while event loop is running
623- std::unique_lock<std::mutex> lock (m_mutex);
624- // Service is no longer running, event loop thread is stopping
625- do_state_update (lock, State::Stopping);
626- lock.unlock ();
624+ {
625+ util::CheckedLockGuard lock (m_mutex);
626+ // Service is no longer running, event loop thread is stopping
627+ m_state = State::Stopping;
628+ }
629+ m_state_cv.notify_all ();
627630 m_logger_ptr->error (" Default event loop exception: " , e.what ());
628631 // If the error was not handled by the thread loop observer, then rethrow
629632 if (!m_observer_ptr->handle_error (e))
@@ -634,12 +637,12 @@ void DefaultSocketProvider::event_loop()
634637
635638void DefaultSocketProvider::stop (bool wait_for_stop)
636639{
637- std::unique_lock<std::mutex> lock (m_mutex);
640+ util::CheckedUniqueLock lock (m_mutex);
638641
639642 // Do nothing if the thread is not started or running or stop has already been called
640643 if (m_state == State::Starting || m_state == State::Running) {
641644 m_logger_ptr->trace (" Default event loop: stop()" );
642- do_state_update (lock, State::Stopping);
645+ do_state_update (State::Stopping);
643646 // Updating state to Stopping will free a start() if it is waiting for the thread to
644647 // start and may cause the thread to exit early before calling service.run()
645648 m_service.stop (); // Unblocks m_service.run()
@@ -661,24 +664,16 @@ void DefaultSocketProvider::stop(bool wait_for_stop)
661664// | | ^
662665// +----------------------+
663666
664- void DefaultSocketProvider::do_state_update (std::unique_lock<std::mutex>&, State new_state)
667+ void DefaultSocketProvider::do_state_update (State new_state)
665668{
666- // m_state_mutex should already be locked...
667669 m_state = new_state;
668670 m_state_cv.notify_all (); // Let any waiters check the state
669671}
670672
671- void DefaultSocketProvider::state_wait_for (std::unique_lock<std::mutex> & lock, State expected_state)
673+ void DefaultSocketProvider::state_wait_for (util::CheckedUniqueLock & lock, State expected_state)
672674{
673- // Check for condition already met or superseded
674- if (m_state >= expected_state)
675- return ;
676-
677- m_state_cv.wait (lock, [this , expected_state]() {
678- // are we there yet?
679- if (m_state < expected_state)
680- return false ;
681- return true ;
675+ m_state_cv.wait (lock.native_handle (), [this , expected_state]() REQUIRES (m_mutex) {
676+ return m_state >= expected_state;
682677 });
683678}
684679
0 commit comments