initial hacks towards a truly thread-safe SafeTime object, using boost::atomic
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 24 Sep 2018 21:34:25 +0000 (17:34 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 27 Sep 2018 15:31:13 +0000 (11:31 -0400)
libs/ardour/ardour/transport_master.h
libs/ardour/mtc_slave.cc

index b41d1070150180e338ca2178a0097666a9d8d0ad..da30abfae9445a65f8d872d1c079ff6f2cd00ee0 100644 (file)
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include <boost/optional.hpp>
+#include <boost/atomic.hpp>
 
 #include <glibmm/threads.h>
 
@@ -282,18 +283,43 @@ class LIBARDOUR_API TransportMaster : public PBD::Stateful {
 };
 
 struct LIBARDOUR_API SafeTime {
-       volatile int guard1;
+       boost::atomic<int> guard1;
        samplepos_t   position;
        samplepos_t   timestamp;
        double       speed;
-       volatile int guard2;
+       boost::atomic<int> guard2;
 
        SafeTime() {
-               guard1 = 0;
+               guard1.store (0);
                position = 0;
                timestamp = 0;
                speed = 0;
-               guard2 = 0;
+               guard2.store (0);
+       }
+
+       SafeTime (SafeTime const & other)
+               : guard1 (other.guard1.load (boost::memory_order_acquire))
+               , position (other.position)
+               , timestamp (other.timestamp)
+               , speed (other.speed)
+               , guard2 (other.guard2.load (boost::memory_order_acquire))
+       {}
+
+       SafeTime& operator= (SafeTime const & other) {
+               guard1 = other.guard1.load (boost::memory_order_acquire);
+               position = other.position;
+               timestamp = other.timestamp;
+               speed = other.speed;
+               guard2 = other.guard2.load (boost::memory_order_acquire);
+               return *this;
+       }
+
+       void update (samplepos_t p, samplepos_t t, double s) {
+               guard1.fetch_add (1, boost::memory_order_acquire);
+               position = p;
+               timestamp = t;
+               speed = s;
+               guard2.fetch_add (1, boost::memory_order_acquire);
        }
 };
 
index a2b73ba2f4b7dcfacd6b14ebd1b9768fd67929cf..7a6d6a6ed6f481e0d931ec0ed8526cb93eb45266 100644 (file)
@@ -273,7 +273,7 @@ MTC_TransportMaster::read_current (SafeTime *st) const
                *st = current;
                tries++;
 
-       } while (st->guard1 != st->guard2);
+       } while (st->guard1.load (boost::memory_order_acquire) != st->guard2.load (boost::memory_order_acquire));
 }
 
 void
@@ -312,11 +312,7 @@ MTC_TransportMaster::update_mtc_qtr (Parser& p, int which_qtr, samplepos_t now)
                mtc_speed = (t1 - t0) / qtr_d;
                DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr sample DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, mtc_speed, e2 - qtr_d));
 
-               current.guard1++;
-               current.position = mtc_frame;
-               current.timestamp = now;
-               current.speed = mtc_speed;
-               current.guard2++;
+               current.update (mtc_frame, now, mtc_speed);
 
                last_inbound_frame = now;
        }
@@ -499,10 +495,7 @@ MTC_TransportMaster::update_mtc_time (const MIDI::byte *msg, bool was_full, samp
                                init_mtc_dll(mtc_frame, qtr);
                                mtc_frame_dll = mtc_frame;
                        }
-                       current.guard1++;
-                       current.position = mtc_frame;
-                       current.timestamp = now;
-                       current.guard2++;
+                       current.update (mtc_frame, now, current.speed);
                        reset_window (mtc_frame);
                }
        }
@@ -525,28 +518,15 @@ MTC_TransportMaster::update_mtc_status (MIDI::MTC_Status status)
 
        switch (status) {
        case MTC_Stopped:
-               current.guard1++;
-               current.position = mtc_frame;
-               current.timestamp = 0;
-               current.speed = 0;
-               current.guard2++;
-
+               current.update (mtc_frame, 0, 0);
                break;
 
        case MTC_Forward:
-               current.guard1++;
-               current.position = mtc_frame;
-               current.timestamp = 0;
-               current.speed = 0;
-               current.guard2++;
+               current.update (mtc_frame, 0, 0);
                break;
 
        case MTC_Backward:
-               current.guard1++;
-               current.position = mtc_frame;
-               current.timestamp = 0;
-               current.speed = 0;
-               current.guard2++;
+               current.update (mtc_frame, 0, 0);
                break;
        }
        busy_guard2++;