World serialization done (not well-tested yet)

This commit is contained in:
2021-03-16 12:19:37 -04:00
parent 7c9fd1e46b
commit a64e339b6b
8 changed files with 111 additions and 52 deletions

View File

@@ -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];

View File

@@ -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();
}

View File

@@ -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();
};

View File

@@ -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);
}
}

View File

@@ -3,15 +3,14 @@
#include <cstdint>
#include <set>
#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

View File

@@ -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.

View File

@@ -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<Tangible> &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;

View File

@@ -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<int64_t, std::unique_ptr<Tangible>> 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