From a64e339b6b011456819708c12ff60effc7cfcf9d Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Tue, 16 Mar 2021 12:19:37 -0400 Subject: [PATCH] World serialization done (not well-tested yet) --- luprex/core/cpp/animqueue.cpp | 1 - luprex/core/cpp/luasnap.cpp | 17 ---------- luprex/core/cpp/luasnap.hpp | 17 ---------- luprex/core/cpp/sched.cpp | 21 +++++++++++- luprex/core/cpp/sched.hpp | 6 ++-- luprex/core/cpp/streambuffer.hpp | 1 + luprex/core/cpp/world.cpp | 57 ++++++++++++++++++++++++++++++-- luprex/core/cpp/world.hpp | 43 ++++++++++++++++++------ 8 files changed, 111 insertions(+), 52 deletions(-) diff --git a/luprex/core/cpp/animqueue.cpp b/luprex/core/cpp/animqueue.cpp index 06d54fb5..e1b3279d 100644 --- a/luprex/core/cpp/animqueue.cpp +++ b/luprex/core/cpp/animqueue.cpp @@ -229,7 +229,6 @@ void AnimQueue::serialize(StreamBuffer *sb) { void AnimQueue::deserialize(StreamBuffer *sb) { size_limit_ = sb->read_int32(); size_t nsteps = sb->read_size(); - steps_.clear(); steps_.resize(nsteps); for (size_t i = 0; i < nsteps; i++) { AnimStep &step = steps_[i]; diff --git a/luprex/core/cpp/luasnap.cpp b/luprex/core/cpp/luasnap.cpp index d745b5a3..c2e66d5b 100644 --- a/luprex/core/cpp/luasnap.cpp +++ b/luprex/core/cpp/luasnap.cpp @@ -122,21 +122,4 @@ void LuaSnap::deserialize(StreamBuffer *sb) { // functionality. So for now, we're sticking with this design, which doesn't // require us to maintain any additional code. -bool LuaSnap::have_snapshot() const { - return snapshot_.write_count() != 0; -} - -void LuaSnap::snapshot() { - assert(snapshot_.write_count() == 0); - serialize(&snapshot_); -} - -void LuaSnap::rollback() { - assert(snapshot_.write_count() != 0); - deserialize(&snapshot_); - assert(snapshot_.at_eof()); - snapshot_.clear(); -} - - diff --git a/luprex/core/cpp/luasnap.hpp b/luprex/core/cpp/luasnap.hpp index 30cf53c4..07d494eb 100644 --- a/luprex/core/cpp/luasnap.hpp +++ b/luprex/core/cpp/luasnap.hpp @@ -20,7 +20,6 @@ class LuaSnap { private: lua_State *state_; - StreamBuffer snapshot_; public: LuaSnap(); @@ -37,22 +36,6 @@ public: // Restore the the lua interpreter given a serialized state. // void deserialize(StreamBuffer *sb); - - // Return true if there's a saved snapshot. - // - bool have_snapshot() const; - - // snapshot the state of the lua interpreter. - // - // If there is already a snapshot, this panics. - // - void snapshot(); - - // Rollback the lua intepreter to the snapshotted state. - // - // If there is no snapshot, this panics. - // - void rollback(); }; diff --git a/luprex/core/cpp/sched.cpp b/luprex/core/cpp/sched.cpp index 703c70a2..e8e25a14 100644 --- a/luprex/core/cpp/sched.cpp +++ b/luprex/core/cpp/sched.cpp @@ -24,4 +24,23 @@ SchedEntry Schedule::pop() { schedule_.erase(schedule_.begin()); return result; } - + +void Schedule::serialize(StreamBuffer *sb) { + sb->write_size(schedule_.size()); + for (const SchedEntry &entry : schedule_) { + sb->write_int64(entry.clock_); + sb->write_int64(entry.thread_id_); + sb->write_int64(entry.place_id_); + } +} + +void Schedule::deserialize(StreamBuffer *sb) { + schedule_.clear(); + size_t nentry = sb->read_size(); + for (size_t i = 0; i < nentry; i++) { + int64_t clock = sb->read_int64(); + int64_t thread_id = sb->read_int64(); + int64_t place_id = sb->read_int64(); + add(clock, thread_id, place_id); + } +} diff --git a/luprex/core/cpp/sched.hpp b/luprex/core/cpp/sched.hpp index d01c93b8..8412b7b4 100644 --- a/luprex/core/cpp/sched.hpp +++ b/luprex/core/cpp/sched.hpp @@ -3,15 +3,14 @@ #include #include +#include "streambuffer.hpp" class SchedEntry { private: friend class Schedule; - int64_t clock_; int64_t thread_id_; int64_t place_id_; - int func_args_; public: int64_t clock() const { return clock_; } @@ -34,6 +33,9 @@ public: void add(int64_t clk, int64_t thid, int64_t plid); bool ready(int64_t clk) const; SchedEntry pop(); + + void serialize(StreamBuffer *sb); + void deserialize(StreamBuffer *sb); }; #endif // SCHED_HPP diff --git a/luprex/core/cpp/streambuffer.hpp b/luprex/core/cpp/streambuffer.hpp index d19b75a1..f38152c5 100644 --- a/luprex/core/cpp/streambuffer.hpp +++ b/luprex/core/cpp/streambuffer.hpp @@ -302,6 +302,7 @@ public: int64_t write_count() const; // Delete all data and (if not fixed-size) free the buffer. + // Also resets the read and write counts. void clear(); // Alloc_space and wrote_space need to be invoked together. diff --git a/luprex/core/cpp/world.cpp b/luprex/core/cpp/world.cpp index f0cf7167..b6afd556 100644 --- a/luprex/core/cpp/world.cpp +++ b/luprex/core/cpp/world.cpp @@ -46,14 +46,11 @@ void Tangible::update_plane_item() { } void Tangible::serialize(StreamBuffer *sb) { - sb->write_int64(id()); anim_queue_.serialize(sb); id_player_pool_.serialize(sb); } void Tangible::deserialize(StreamBuffer *sb) { - int64_t id = sb->read_int64(); - plane_item_.set_id(id); anim_queue_.deserialize(sb); id_player_pool_.deserialize(sb); update_plane_item(); @@ -365,6 +362,60 @@ void World::run_scheduled_threads(int64_t clk) { LS.result(); } +void World::serialize(StreamBuffer *sb) { + int64_t wc0 = sb->write_count(); + lua_snap_.serialize(sb); + id_global_pool_.serialize(sb); + thread_sched_.serialize(sb); + sb->write_size(tangibles_.size()); + for (const auto &p : tangibles_) { + sb->write_int64(p.first); + p.second->serialize(sb); + } + int64_t wc1 = sb->write_count(); + std::cerr << "World serialized to " << wc1-wc0 << " bytes." << std::endl; +} + +void World::deserialize(StreamBuffer *sb) { + lua_snap_.deserialize(sb); + id_global_pool_.deserialize(sb); + thread_sched_.deserialize(sb); + // Mark all tangibles for deletion by setting ID to zero. + for (const auto &p : tangibles_) { + p.second->plane_item_.set_id(0); + } + // Deserialize tangibles. + size_t ntan = sb->read_size(); + for (size_t i = 0; i < ntan; i++) { + int64_t id = sb->read_int64(); + std::unique_ptr &t = tangibles_[id]; + if (t == nullptr) { + t.reset(new Tangible(this, id)); + } else { + t->plane_item_.set_id(id); + } + t->deserialize(sb); + } + // Delete tangibles that didn't get deserialized. + for (auto iter = tangibles_.begin(); iter != tangibles_.end(); ) { + if (iter->second->plane_item_.id() == 0) { + tangibles_.erase(iter++); + } else { + ++iter; + } + } +} + +void World::snapshot() { + snapshot_.clear(); + serialize(&snapshot_); +} + +void World::rollback() { + assert(!snapshot_.at_eof()); + deserialize(&snapshot_); +} + LuaDefine(tangible_xyz, "c") { LuaArg tanobj; LuaRet X, Y, Z; diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index fe511685..4315e435 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -18,6 +18,25 @@ class World; class Tangible { +private: + friend class World; + + // Serialize and deserialize + // + // The tangible's ID is not serialized. When you serialize a tangible, you + // should probably serialize the ID separately. + // + // The Lua portion of the tangible is not serialized here. Instead, the lua + // portion is serialized when you serialize the lua state as a whole. + // + // PlaneItem is not serialized. The deserialize routine rebuilds the + // PlaneItem from the AnimQueue. + // + // World pointer is not serialized. + // + void serialize(StreamBuffer *sb); + void deserialize(StreamBuffer *sb); + public: // Always points back to the world model. World *world_; @@ -50,15 +69,6 @@ public: int64_t id() { return plane_item_.id(); } void be_a_player(); void update_plane_item(); - - // Serialize and deserialize - // - // PlaneItem is not serialized except the ID. The deserialize routine - // rebuilds the PlaneItem from the AnimQueue. World pointer is not - // serialized. - // - void serialize(StreamBuffer *sb); - void deserialize(StreamBuffer *sb); }; class World { @@ -75,6 +85,9 @@ public: // SourceDB source_db_; PlaneMap plane_map_; + + // Tangibles table. + // std::unordered_map> tangibles_; // Thread schedule: must include every thread, except @@ -82,6 +95,9 @@ public: // Schedule thread_sched_; + // Serialized snapshot of world model. + StreamBuffer snapshot_; + void run_scheduled_threads(int64_t clk); public: // Constructor. @@ -158,10 +174,15 @@ public: static void store_global_pointer(lua_State *L, World *w); static World *fetch_global_pointer(lua_State *L); + // Serialize and deserialize. + // + void serialize(StreamBuffer *sb); + void deserialize(StreamBuffer *sb); + // Snapshot and rollback - temporary. // - void snapshot() { lua_snap_.snapshot(); } - void rollback() { lua_snap_.rollback(); } + void snapshot(); + void rollback(); }; #endif // WORLD_HPP