diff --git a/Storage/Disk/Disk.hpp b/Storage/Disk/Disk.hpp index c929bff3a..95e5bc4a9 100644 --- a/Storage/Disk/Disk.hpp +++ b/Storage/Disk/Disk.hpp @@ -23,7 +23,9 @@ namespace Disk { class Disk { public: - virtual ~Disk() {} + virtual ~Disk() { + flush_tracks(); + } /*! @returns the number of discrete positions that this disk uses to model its complete surface area. diff --git a/Storage/Disk/DiskImage/DiskImage.hpp b/Storage/Disk/DiskImage/DiskImage.hpp index 1b4a26229..011b5e5ac 100644 --- a/Storage/Disk/DiskImage/DiskImage.hpp +++ b/Storage/Disk/DiskImage/DiskImage.hpp @@ -66,6 +66,7 @@ class DiskImage { class DiskImageHolderBase: public Disk { protected: + std::set unwritten_tracks_; std::map> cached_tracks_; std::unique_ptr update_queue_; }; diff --git a/Storage/Disk/DiskImage/DiskImageImplementation.hpp b/Storage/Disk/DiskImage/DiskImageImplementation.hpp index be56720cb..9ef1da3d3 100644 --- a/Storage/Disk/DiskImage/DiskImageImplementation.hpp +++ b/Storage/Disk/DiskImage/DiskImageImplementation.hpp @@ -19,18 +19,30 @@ template bool DiskImageHolder::get_is_read_only() { } template void DiskImageHolder::flush_tracks() { + if(!unwritten_tracks_.empty()) { + if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue); + + using TrackMap = std::map>; + std::shared_ptr track_copies(new TrackMap); + for(auto &address : unwritten_tracks_) { + track_copies->insert(std::make_pair(address, cached_tracks_[address]->clone())); + } + unwritten_tracks_.clear(); + + update_queue_->enqueue([this, track_copies]() { + // TODO: communicate these as a batch, not one by one. + for(auto &pair : *track_copies) { + disk_image_.set_track_at_position(pair.first, pair.second); + } + }); + } } template void DiskImageHolder::set_track_at_position(Track::Address address, const std::shared_ptr &track) { if(disk_image_.get_is_read_only()) return; + unwritten_tracks_.insert(address); cached_tracks_[address] = track; - - if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue); - std::shared_ptr track_copy(track->clone()); - update_queue_->enqueue([this, address, track_copy] { - disk_image_.set_track_at_position(address, track_copy); - }); } template std::shared_ptr DiskImageHolder::get_track_at_position(Track::Address address) {