@@ -1887,8 +1887,9 @@ Viewer::Viewer(std::unique_ptr<PlatformUIAdapter> platform_ui_adapter, MujocoEnv
18871887// operations which require holding the mutex, prevents racing with physics thread
18881888void Viewer::Sync (bool state_only)
18891889{
1890- MutexLock lock (this ->mtx );
1891- MutexLock lock_env (env_->physics_thread_mutex_ );
1890+ MutexLock lock_env (env_->physics_thread_mutex_ , std::defer_lock);
1891+ MutexLock lock (this ->mtx , std::defer_lock);
1892+ std::lock (lock_env, lock); // avoid deadlock
18921893 if (!m_ || !d_) {
18931894 return ;
18941895 }
@@ -2263,33 +2264,40 @@ void Viewer::LoadMessage(const char *displayed_filename)
22632264
22642265 {
22652266 MutexLock lock (mtx);
2266- this ->loadrequest = 3 ;
2267+ this ->loadrequest . store ( 3 ) ;
22672268 }
22682269}
22692270
22702271void Viewer::LoadMessageClear ()
22712272{
22722273 {
22732274 MutexLock lock (mtx);
2274- this ->loadrequest = 0 ;
2275+ this ->loadrequest . store ( 0 ) ;
22752276 }
22762277}
22772278
22782279void Viewer::Load (mjModelPtr m, mjDataPtr d, const char *displayed_filename)
22792280{
2281+ ROS_DEBUG (" Model load requested from physics thread" );
22802282 this ->mnew_ = std::move (m);
22812283 this ->dnew_ = std::move (d);
22822284 mju::strcpy_arr (this ->filename , displayed_filename);
22832285
2286+ std::future<void > reload_future;
22842287 {
2288+ // Lock mutex to create promise
22852289 MutexLock lock (mtx);
2286- this ->loadrequest = 2 ;
2287-
2288- // Wait for the render thread to be done loading
2289- // so that we know the old model and data's memory can
2290- // be freed by the other thread (sometimes python)
2291- cond_loadrequest.wait (lock, [this ]() { return this ->loadrequest == 0 ; });
2290+ reload_promise_.emplace ();
2291+ reload_future = reload_promise_->get_future ();
22922292 }
2293+ this ->loadrequest .store (2 );
2294+
2295+ // Wait for the render thread to be done loading
2296+ // so that we know the old model and data's memory can
2297+ // be freed by the other thread (sometimes python)
2298+ reload_future.wait ();
2299+ reload_promise_.reset ();
2300+ ROS_DEBUG (" Model load completed in physics thread" );
22932301}
22942302
22952303void Viewer::LoadOnRenderThread ()
@@ -2475,8 +2483,10 @@ void Viewer::LoadOnRenderThread()
24752483
24762484 // clear request
24772485 ROS_DEBUG (" Notifying load request complete" );
2478- this ->loadrequest = 0 ;
2479- cond_loadrequest.notify_all ();
2486+ this ->loadrequest .store (0 );
2487+ if (reload_promise_) {
2488+ reload_promise_->set_value ();
2489+ }
24802490
24812491 // set real time index
24822492 int numclicks = sizeof (MujocoEnv::percentRealTime) / sizeof (MujocoEnv::percentRealTime[0 ]);
@@ -2516,7 +2526,7 @@ void Viewer::Render()
25162526 mjr_rectangle (rect, 0 .2f , 0 .3f , 0 .4f , 1 );
25172527
25182528 // label
2519- if (this ->loadrequest ) {
2529+ if (this ->loadrequest . load () ) {
25202530 mjr_overlay (mjFONT_BIG, mjGRID_TOP, smallrect, " LOADING..." , nullptr , &this ->platform_ui ->mjr_context ());
25212531 } else {
25222532 char intro_message[Viewer::kMaxFilenameLength ];
@@ -2636,9 +2646,9 @@ void Viewer::Render()
26362646 }
26372647
26382648 // show pause/loading label
2639- if (!this ->run || this ->loadrequest ) {
2649+ if (!this ->run || this ->loadrequest . load () ) {
26402650 char label[30 ] = { ' \0 ' };
2641- if (this ->loadrequest ) {
2651+ if (this ->loadrequest . load () ) {
26422652 std::snprintf (label, sizeof (label), " LOADING..." );
26432653 } else if (this ->scrub_index == 0 ) {
26442654 std::snprintf (label, sizeof (label), " PAUSE" );
@@ -2853,10 +2863,12 @@ void Viewer::RenderLoop()
28532863 const MutexLock lock (this ->mtx );
28542864
28552865 // Load model (not on first pass, to show "loading" label)
2856- if (this ->loadrequest == 1 ) {
2866+ if (this ->loadrequest .load () == 1 ) {
2867+ ROS_DEBUG (" Model load triggered in render thread" );
28572868 this ->LoadOnRenderThread ();
2858- } else if (this ->loadrequest == 2 ) {
2859- this ->loadrequest = 1 ;
2869+ } else if (this ->loadrequest .load () == 2 ) {
2870+ ROS_DEBUG (" Model load announced in render thread" );
2871+ this ->loadrequest .store (1 );
28602872 }
28612873
28622874 // Poll and handle events
0 commit comments