From 6fc692cd347b52f89a06489eaa1f04d95eed37d1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 29 Dec 2016 22:15:58 -0500 Subject: [PATCH] Attempted to switch to an asynchronous means for continuous file updates. Testing with SSD, as usual. --- Storage/Disk/Disk.cpp | 20 ++++++------ Storage/Disk/Disk.hpp | 18 +++++------ Storage/Disk/Formats/AcornADF.cpp | 39 +++++++++++------------ Storage/Disk/Formats/SSD.cpp | 51 ++++++++++++++++++------------- Storage/Disk/Formats/SSD.hpp | 2 ++ 5 files changed, 69 insertions(+), 61 deletions(-) diff --git a/Storage/Disk/Disk.cpp b/Storage/Disk/Disk.cpp index 96953f5bd..6938014e7 100644 --- a/Storage/Disk/Disk.cpp +++ b/Storage/Disk/Disk.cpp @@ -21,7 +21,11 @@ void Disk::set_track_at_position(unsigned int head, unsigned int position, const int address = get_id_for_track_at_position(head, position); cached_tracks_[address] = track; - modified_tracks_.insert(address); + + if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue); + update_queue_->enqueue([this, head, position, track] { + store_updated_track_at_position(head, position, track, file_access_mutex_); + }); } std::shared_ptr Disk::get_track_at_position(unsigned int head, unsigned int position) @@ -30,21 +34,15 @@ std::shared_ptr Disk::get_track_at_position(unsigned int head, unsigned i std::map>::iterator cached_track = cached_tracks_.find(address); if(cached_track != cached_tracks_.end()) return cached_track->second; + std::lock_guard lock_guard(file_access_mutex_); std::shared_ptr track = get_uncached_track_at_position(head, position); cached_tracks_[address] = track; return track; } -std::shared_ptr Disk::get_modified_track_at_position(unsigned int head, unsigned int position) -{ - int address = get_id_for_track_at_position(head, position); - if(modified_tracks_.find(address) == modified_tracks_.end()) return nullptr; - std::map>::iterator cached_track = cached_tracks_.find(address); - if(cached_track == cached_tracks_.end()) return nullptr; - return cached_track->second; -} +void Disk::store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track, std::mutex &file_access_mutex) {} -bool Disk::get_is_modified() +void Disk::flush_updates() { - return !modified_tracks_.empty(); + if(update_queue_) update_queue_->flush(); } diff --git a/Storage/Disk/Disk.hpp b/Storage/Disk/Disk.hpp index 7b435d838..b23081a04 100644 --- a/Storage/Disk/Disk.hpp +++ b/Storage/Disk/Disk.hpp @@ -9,10 +9,13 @@ #ifndef Disk_hpp #define Disk_hpp -#include #include +#include +#include #include + #include "../Storage.hpp" +#include "../../Concurrency/AsyncTaskQueue.hpp" namespace Storage { namespace Disk { @@ -107,20 +110,15 @@ class Disk { */ virtual std::shared_ptr get_uncached_track_at_position(unsigned int head, unsigned int position) = 0; - /*! - @returns @c true if any calls to set_track_at_position occurred; @c false otherwise. - */ - bool get_is_modified(); - /*! - @returns the @c Track at @c position underneath @c head if a modification was written there. - */ - std::shared_ptr get_modified_track_at_position(unsigned int head, unsigned int position); + virtual void store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track, std::mutex &file_access_mutex); + void flush_updates(); private: std::map> cached_tracks_; - std::set modified_tracks_; int get_id_for_track_at_position(unsigned int head, unsigned int position); + std::mutex file_access_mutex_; + std::unique_ptr update_queue_; }; } diff --git a/Storage/Disk/Formats/AcornADF.cpp b/Storage/Disk/Formats/AcornADF.cpp index b1e8d0794..9615139f9 100644 --- a/Storage/Disk/Formats/AcornADF.cpp +++ b/Storage/Disk/Formats/AcornADF.cpp @@ -39,25 +39,26 @@ AcornADF::AcornADF(const char *file_name) : AcornADF::~AcornADF() { - if(get_is_modified()) - { - for(unsigned int head = 0; head < get_head_count(); head++) - { - for(unsigned int track = 0; track < get_head_position_count(); track++) - { - std::shared_ptr modified_track = get_modified_track_at_position(head, track); - if(modified_track) - { - Storage::Encodings::MFM::Parser parser(true, modified_track); - for(unsigned int c = 0; c < sectors_per_track; c++) - { - std::shared_ptr sector = parser.get_sector((uint8_t)track, (uint8_t)c); - printf("Sector %d: %p\n", c, sector.get()); - } - } - } - } - } + flush_updates(); +// if(get_is_modified()) +// { +// for(unsigned int head = 0; head < get_head_count(); head++) +// { +// for(unsigned int track = 0; track < get_head_position_count(); track++) +// { +// std::shared_ptr modified_track = get_modified_track_at_position(head, track); +// if(modified_track) +// { +// Storage::Encodings::MFM::Parser parser(true, modified_track); +// for(unsigned int c = 0; c < sectors_per_track; c++) +// { +// std::shared_ptr sector = parser.get_sector((uint8_t)track, (uint8_t)c); +// printf("Sector %d: %p\n", c, sector.get()); +// } +// } +// } +// } +// } } unsigned int AcornADF::get_head_position_count() diff --git a/Storage/Disk/Formats/SSD.cpp b/Storage/Disk/Formats/SSD.cpp index 7493c2419..b7977df58 100644 --- a/Storage/Disk/Formats/SSD.cpp +++ b/Storage/Disk/Formats/SSD.cpp @@ -32,27 +32,10 @@ SSD::SSD(const char *file_name) : SSD::~SSD() { - if(get_is_modified()) - { - for(unsigned int head = 0; head < head_count_; head++) - { - for(unsigned int track = 0; track < track_count_; track++) - { - std::shared_ptr modified_track = get_modified_track_at_position(head, track); - if(modified_track) - { - Storage::Encodings::MFM::Parser parser(false, modified_track); - for(unsigned int c = 0; c < 10; c++) - { - std::shared_ptr sector = parser.get_sector((uint8_t)track, (uint8_t)c); - printf("Sector %d: %p\n", c, sector.get()); - } - } - } - } - } + flush_updates(); } + unsigned int SSD::get_head_position_count() { return track_count_; @@ -68,13 +51,17 @@ bool SSD::get_is_read_only() return is_read_only_; } +long SSD::get_file_offset_for_position(unsigned int head, unsigned int position) +{ + return (position * head_count_ + head) * 256 * 10; +} + std::shared_ptr SSD::get_uncached_track_at_position(unsigned int head, unsigned int position) { std::shared_ptr track; if(head >= head_count_) return track; - long file_offset = (position * head_count_ + head) * 256 * 10; - fseek(file_, file_offset, SEEK_SET); + fseek(file_, get_file_offset_for_position(head, position), SEEK_SET); std::vector sectors; for(int sector = 0; sector < 10; sector++) @@ -99,3 +86,25 @@ std::shared_ptr SSD::get_uncached_track_at_position(unsigned int head, un return track; } + +void SSD::store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track, std::mutex &file_access_mutex) +{ + std::vector parsed_track; + Storage::Encodings::MFM::Parser parser(false, track); + for(unsigned int c = 0; c < 10; c++) + { + std::shared_ptr sector = parser.get_sector((uint8_t)position, (uint8_t)c); + if(sector) + { + parsed_track.insert(parsed_track.end(), sector->data.begin(), sector->data.end()); + } + else + { + parsed_track.resize(parsed_track.size() + 256); + } + } + + std::lock_guard lock_guard(file_access_mutex); + fseek(file_, get_file_offset_for_position(head, position), SEEK_SET); + fwrite(parsed_track.data(), 1, parsed_track.size(), file_); +} diff --git a/Storage/Disk/Formats/SSD.hpp b/Storage/Disk/Formats/SSD.hpp index b7c21ccb3..0e806a147 100644 --- a/Storage/Disk/Formats/SSD.hpp +++ b/Storage/Disk/Formats/SSD.hpp @@ -39,7 +39,9 @@ class SSD: public Disk, public Storage::FileHolder { bool get_is_read_only(); private: + void store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track, std::mutex &file_access_mutex); std::shared_ptr get_uncached_track_at_position(unsigned int head, unsigned int position); + long get_file_offset_for_position(unsigned int head, unsigned int position); unsigned int head_count_; unsigned int track_count_; };