World serialization done (not well-tested yet)
This commit is contained in:
@@ -229,7 +229,6 @@ void AnimQueue::serialize(StreamBuffer *sb) {
|
|||||||
void AnimQueue::deserialize(StreamBuffer *sb) {
|
void AnimQueue::deserialize(StreamBuffer *sb) {
|
||||||
size_limit_ = sb->read_int32();
|
size_limit_ = sb->read_int32();
|
||||||
size_t nsteps = sb->read_size();
|
size_t nsteps = sb->read_size();
|
||||||
steps_.clear();
|
|
||||||
steps_.resize(nsteps);
|
steps_.resize(nsteps);
|
||||||
for (size_t i = 0; i < nsteps; i++) {
|
for (size_t i = 0; i < nsteps; i++) {
|
||||||
AnimStep &step = steps_[i];
|
AnimStep &step = steps_[i];
|
||||||
|
|||||||
@@ -122,21 +122,4 @@ void LuaSnap::deserialize(StreamBuffer *sb) {
|
|||||||
// functionality. So for now, we're sticking with this design, which doesn't
|
// functionality. So for now, we're sticking with this design, which doesn't
|
||||||
// require us to maintain any additional code.
|
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
class LuaSnap {
|
class LuaSnap {
|
||||||
private:
|
private:
|
||||||
lua_State *state_;
|
lua_State *state_;
|
||||||
StreamBuffer snapshot_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LuaSnap();
|
LuaSnap();
|
||||||
@@ -37,22 +36,6 @@ public:
|
|||||||
// Restore the the lua interpreter given a serialized state.
|
// Restore the the lua interpreter given a serialized state.
|
||||||
//
|
//
|
||||||
void deserialize(StreamBuffer *sb);
|
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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,3 +25,22 @@ SchedEntry Schedule::pop() {
|
|||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,15 +3,14 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include "streambuffer.hpp"
|
||||||
|
|
||||||
class SchedEntry {
|
class SchedEntry {
|
||||||
private:
|
private:
|
||||||
friend class Schedule;
|
friend class Schedule;
|
||||||
|
|
||||||
int64_t clock_;
|
int64_t clock_;
|
||||||
int64_t thread_id_;
|
int64_t thread_id_;
|
||||||
int64_t place_id_;
|
int64_t place_id_;
|
||||||
int func_args_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int64_t clock() const { return clock_; }
|
int64_t clock() const { return clock_; }
|
||||||
@@ -34,6 +33,9 @@ public:
|
|||||||
void add(int64_t clk, int64_t thid, int64_t plid);
|
void add(int64_t clk, int64_t thid, int64_t plid);
|
||||||
bool ready(int64_t clk) const;
|
bool ready(int64_t clk) const;
|
||||||
SchedEntry pop();
|
SchedEntry pop();
|
||||||
|
|
||||||
|
void serialize(StreamBuffer *sb);
|
||||||
|
void deserialize(StreamBuffer *sb);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SCHED_HPP
|
#endif // SCHED_HPP
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ public:
|
|||||||
int64_t write_count() const;
|
int64_t write_count() const;
|
||||||
|
|
||||||
// Delete all data and (if not fixed-size) free the buffer.
|
// Delete all data and (if not fixed-size) free the buffer.
|
||||||
|
// Also resets the read and write counts.
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// Alloc_space and wrote_space need to be invoked together.
|
// Alloc_space and wrote_space need to be invoked together.
|
||||||
|
|||||||
@@ -46,14 +46,11 @@ void Tangible::update_plane_item() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Tangible::serialize(StreamBuffer *sb) {
|
void Tangible::serialize(StreamBuffer *sb) {
|
||||||
sb->write_int64(id());
|
|
||||||
anim_queue_.serialize(sb);
|
anim_queue_.serialize(sb);
|
||||||
id_player_pool_.serialize(sb);
|
id_player_pool_.serialize(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tangible::deserialize(StreamBuffer *sb) {
|
void Tangible::deserialize(StreamBuffer *sb) {
|
||||||
int64_t id = sb->read_int64();
|
|
||||||
plane_item_.set_id(id);
|
|
||||||
anim_queue_.deserialize(sb);
|
anim_queue_.deserialize(sb);
|
||||||
id_player_pool_.deserialize(sb);
|
id_player_pool_.deserialize(sb);
|
||||||
update_plane_item();
|
update_plane_item();
|
||||||
@@ -365,6 +362,60 @@ void World::run_scheduled_threads(int64_t clk) {
|
|||||||
LS.result();
|
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") {
|
LuaDefine(tangible_xyz, "c") {
|
||||||
LuaArg tanobj;
|
LuaArg tanobj;
|
||||||
LuaRet X, Y, Z;
|
LuaRet X, Y, Z;
|
||||||
|
|||||||
@@ -18,6 +18,25 @@
|
|||||||
class World;
|
class World;
|
||||||
|
|
||||||
class Tangible {
|
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:
|
public:
|
||||||
// Always points back to the world model.
|
// Always points back to the world model.
|
||||||
World *world_;
|
World *world_;
|
||||||
@@ -50,15 +69,6 @@ public:
|
|||||||
int64_t id() { return plane_item_.id(); }
|
int64_t id() { return plane_item_.id(); }
|
||||||
void be_a_player();
|
void be_a_player();
|
||||||
void update_plane_item();
|
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 {
|
class World {
|
||||||
@@ -75,6 +85,9 @@ public:
|
|||||||
//
|
//
|
||||||
SourceDB source_db_;
|
SourceDB source_db_;
|
||||||
PlaneMap plane_map_;
|
PlaneMap plane_map_;
|
||||||
|
|
||||||
|
// Tangibles table.
|
||||||
|
//
|
||||||
std::unordered_map<int64_t, std::unique_ptr<Tangible>> tangibles_;
|
std::unordered_map<int64_t, std::unique_ptr<Tangible>> tangibles_;
|
||||||
|
|
||||||
// Thread schedule: must include every thread, except
|
// Thread schedule: must include every thread, except
|
||||||
@@ -82,6 +95,9 @@ public:
|
|||||||
//
|
//
|
||||||
Schedule thread_sched_;
|
Schedule thread_sched_;
|
||||||
|
|
||||||
|
// Serialized snapshot of world model.
|
||||||
|
StreamBuffer snapshot_;
|
||||||
|
|
||||||
void run_scheduled_threads(int64_t clk);
|
void run_scheduled_threads(int64_t clk);
|
||||||
public:
|
public:
|
||||||
// Constructor.
|
// Constructor.
|
||||||
@@ -158,10 +174,15 @@ public:
|
|||||||
static void store_global_pointer(lua_State *L, World *w);
|
static void store_global_pointer(lua_State *L, World *w);
|
||||||
static World *fetch_global_pointer(lua_State *L);
|
static World *fetch_global_pointer(lua_State *L);
|
||||||
|
|
||||||
|
// Serialize and deserialize.
|
||||||
|
//
|
||||||
|
void serialize(StreamBuffer *sb);
|
||||||
|
void deserialize(StreamBuffer *sb);
|
||||||
|
|
||||||
// Snapshot and rollback - temporary.
|
// Snapshot and rollback - temporary.
|
||||||
//
|
//
|
||||||
void snapshot() { lua_snap_.snapshot(); }
|
void snapshot();
|
||||||
void rollback() { lua_snap_.rollback(); }
|
void rollback();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WORLD_HPP
|
#endif // WORLD_HPP
|
||||||
|
|||||||
Reference in New Issue
Block a user