diff --git a/panda/src/putil/clockObject.I b/panda/src/putil/clockObject.I index d9bcac3a7c..f8a0bbc02b 100644 --- a/panda/src/putil/clockObject.I +++ b/panda/src/putil/clockObject.I @@ -213,10 +213,12 @@ check_errors(Thread *current_thread) { */ INLINE ClockObject *ClockObject:: get_global_clock() { - if (_global_clock == (ClockObject *)NULL) { + ClockObject *clock = (ClockObject *)AtomicAdjust::get_ptr(_global_clock); + if (UNLIKELY(clock == nullptr)) { make_global_clock(); + clock = (ClockObject *)_global_clock; } - return _global_clock; + return clock; } /** diff --git a/panda/src/putil/clockObject.cxx b/panda/src/putil/clockObject.cxx index d53f4ea329..09353ab739 100644 --- a/panda/src/putil/clockObject.cxx +++ b/panda/src/putil/clockObject.cxx @@ -21,21 +21,16 @@ void (*ClockObject::_start_clock_wait)() = ClockObject::dummy_clock_wait; void (*ClockObject::_start_clock_busy_wait)() = ClockObject::dummy_clock_wait; void (*ClockObject::_stop_clock_wait)() = ClockObject::dummy_clock_wait; -ClockObject *ClockObject::_global_clock; +AtomicAdjust::Pointer ClockObject::_global_clock = nullptr; TypeHandle ClockObject::_type_handle; /** * */ ClockObject:: -ClockObject() : _ticks(get_class_type()) { +ClockObject(Mode mode) : _ticks(get_class_type()), _mode(mode) { _true_clock = TrueClock::get_global_ptr(); - // Each clock except for the application global clock is created in M_normal - // mode. The application global clock is later reset to respect clock_mode, - // which comes from the Config.prc file. - _mode = M_normal; - _start_short_time = _true_clock->get_short_time(); _start_long_time = _true_clock->get_long_time(); _actual_frame_time = 0.0; @@ -523,7 +518,7 @@ wait_until(double want_time) { */ void ClockObject:: make_global_clock() { - nassertv(_global_clock == (ClockObject *)NULL); + nassertv(_global_clock == nullptr); ConfigVariableEnum clock_mode ("clock-mode", ClockObject::M_normal, @@ -532,9 +527,13 @@ make_global_clock() { "effects like simulated reduced frame rate. See " "ClockObject::set_mode().")); - _global_clock = new ClockObject; - _global_clock->set_mode(clock_mode); - _global_clock->ref(); + ClockObject *clock = new ClockObject(clock_mode); + clock->local_object(); + + if (AtomicAdjust::compare_and_exchange_ptr(_global_clock, nullptr, clock) != nullptr) { + // Another thread beat us to it. + delete clock; + } } /** diff --git a/panda/src/putil/clockObject.h b/panda/src/putil/clockObject.h index ca7e3d2116..bcea511f29 100644 --- a/panda/src/putil/clockObject.h +++ b/panda/src/putil/clockObject.h @@ -68,7 +68,7 @@ PUBLISHED: M_integer_limited, }; - ClockObject(); + ClockObject(Mode mode = M_normal); ClockObject(const ClockObject ©); INLINE ~ClockObject(); @@ -172,7 +172,7 @@ private: typedef CycleDataWriter CDWriter; typedef CycleDataStageReader CDStageReader; - static ClockObject *_global_clock; + static AtomicAdjust::Pointer _global_clock; public: static TypeHandle get_class_type() {