]> git.tdb.fi Git - libs/game.git/commitdiff
Re-separate transaction unblock/block from prepare/commit
authorMikko Rasa <tdb@tdb.fi>
Sun, 23 Mar 2025 11:38:45 +0000 (13:38 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 23 Mar 2025 12:11:22 +0000 (14:11 +0200)
Multithreaded ticks may require waiting or even running other systems in
between a system's tick finishing and the changes being committed.

Customized transactors must explicitly unblock and re-block access if
they wish to modify the component during commit.

source/game/systemscheduler.cpp
source/game/transactor.h
source/game/transformpropagator.cpp

index 329e4a1e15ec345701f38c2f338790573fe35e6a..8387c35bfcefb93bcc1dd79f833a76884ffeb1fa 100644 (file)
@@ -167,7 +167,10 @@ void SystemScheduler::run_system(size_t index, Time::TimeDelta dt)
        System &sys = *nodes[index].system;
        for(const System::Dependency &d: sys.get_dependencies())
                if(Transactor *tract = d.get_transactor())
+               {
                        tract->prepare(d.get_transact_mode());
+                       tract->unblock(d.get_transact_mode());
+               }
 
        try
        {
@@ -180,7 +183,10 @@ void SystemScheduler::run_system(size_t index, Time::TimeDelta dt)
 
        for(const System::Dependency &d: sys.get_dependencies())
                if(Transactor *tract = d.get_transactor())
+               {
+                       tract->block(d.get_transact_mode());
                        tract->commit(d.get_transact_mode());
+               }
 }
 
 } // namespace Msp::Game
index d502d7bd8308b9574d167dcf88de92a3ba77ae3b..d278a9a8992c6d92d090ee7b8f7c136af5306aa7 100644 (file)
@@ -26,6 +26,13 @@ public:
        virtual ~Transactor() = default;
 
        virtual void prepare(Mode) = 0;
+#ifdef DEBUG
+       virtual void unblock(Mode) = 0;
+       virtual void block(Mode) = 0;
+#else
+       void unblock(Mode) { }
+       void block(Mode) { }
+#endif
        virtual void commit(Mode) = 0;
 };
 
@@ -36,35 +43,45 @@ public:
        BasicTransactor(Stage &s): Transactor(s) { }
 
        void prepare(Mode) override;
+#ifdef DEBUG
+       void unblock(Mode) override;
+       void block(Mode) override;
+#endif
        void commit(Mode) override;
 };
 
 template<typename T>
 void BasicTransactor<T>::prepare(Mode mode)
 {
+       if(mode&WRITE)
+               stage.iterate_objects<T>([](T &c){ c.prepare_tick(); });
+}
+
 #ifdef DEBUG
+template<typename T>
+void BasicTransactor<T>::unblock(Mode mode)
+{
        if(mode&READ)
                AccessGuard::get_instance().unblock<AccessGuard::Read<typename T::Data>>();
        if(mode&WRITE)
                AccessGuard::get_instance().unblock<AccessGuard::Write<typename T::Data>>();
-#endif
-
-       if(mode&WRITE)
-               stage.iterate_objects<T>([](T &c){ c.prepare_tick(); });
 }
 
 template<typename T>
-void BasicTransactor<T>::commit(Mode mode)
+void BasicTransactor<T>::block(Mode mode)
 {
-       if(mode&WRITE)
-               stage.iterate_objects<T>([](T &c){ c.commit_tick(); });
-
-#ifdef DEBUG
        if(mode&READ)
                AccessGuard::get_instance().block<AccessGuard::Read<typename T::Data>>();
        if(mode&WRITE)
                AccessGuard::get_instance().block<AccessGuard::Write<typename T::Data>>();
+}
 #endif
+
+template<typename T>
+void BasicTransactor<T>::commit(Mode mode)
+{
+       if(mode&WRITE)
+               stage.iterate_objects<T>([](T &c){ c.commit_tick(); });
 }
 
 } // namespace Msp::Game
index 86da2d149c83dfdddbed117fd1ee5fc59a57ea9b..1052f089ee34dc2f0d8baec11904d2c193a84a4a 100644 (file)
@@ -20,11 +20,13 @@ void TransformPropagator::commit(Mode mode)
 {
        if(mode&WRITE)
        {
+               unblock(RDWR);
                if(transforms_dirty)
                        rebuild_transform_order();
 
                for(const ParentedTransform &t: transforms)
                        t.transform->update_world_matrix(t.parent.get());
+               block(RDWR);
        }
 
        BasicTransactor::commit(mode);