From d72dad2d1afb4f11f3684b10fc76fe250c1ba7f8 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 22 Sep 2017 22:46:31 -0400 Subject: [PATCH] Severs the DiskImage implementation from its public header file. --- .../Clock Signal.xcodeproj/project.pbxproj | 2 + Storage/Disk/DiskImage/DiskImage.hpp | 57 +++---------------- .../DiskImage/DiskImageImplementation.hpp | 50 ++++++++++++++++ 3 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 Storage/Disk/DiskImage/DiskImageImplementation.hpp diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index b10646334..98d5ffd92 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -612,6 +612,7 @@ 4B45189C1F75FD1C00926311 /* SingleTrackDisk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SingleTrackDisk.cpp; sourceTree = ""; }; 4B45189D1F75FD1C00926311 /* SingleTrackDisk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SingleTrackDisk.hpp; sourceTree = ""; }; 4B4518A71F76004200926311 /* TapeParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TapeParser.hpp; path = Parsers/TapeParser.hpp; sourceTree = ""; }; + 4B4518A81F76022000926311 /* DiskImageImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiskImageImplementation.hpp; sourceTree = ""; }; 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AY38910.cpp; path = AY38910/AY38910.cpp; sourceTree = ""; }; 4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AY38910.hpp; path = AY38910/AY38910.hpp; sourceTree = ""; }; 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vic20.cpp; sourceTree = ""; }; @@ -1443,6 +1444,7 @@ children = ( 4B45188A1F75FD1B00926311 /* DiskImage.cpp */, 4B45188B1F75FD1B00926311 /* DiskImage.hpp */, + 4B4518A81F76022000926311 /* DiskImageImplementation.hpp */, 4B45188C1F75FD1B00926311 /* Formats */, ); path = DiskImage; diff --git a/Storage/Disk/DiskImage/DiskImage.hpp b/Storage/Disk/DiskImage/DiskImage.hpp index 21a5482bc..8a344cb98 100644 --- a/Storage/Disk/DiskImage/DiskImage.hpp +++ b/Storage/Disk/DiskImage/DiskImage.hpp @@ -19,16 +19,11 @@ namespace Storage { namespace Disk { /*! - Models a disk as a collection of tracks, providing a range of possible track positions and allowing - a point sampling of the track beneath any of those positions (if any). + Models a disk image as a collection of tracks, plus a range of possible track positions. The intention is not that tracks necessarily be evenly spaced; a head_position_count of 3 wih track A appearing in positions 0 and 1, and track B appearing in position 2 is an appropriate use of this API if it matches the media. - - The track returned is point sampled only; if a particular disk drive has a sufficiently large head to - pick up multiple tracks at once then the drive responsible for asking for multiple tracks and for - merging the results. */ class DiskImage { public: @@ -70,10 +65,14 @@ class DiskImageHolderBase: public Disk { protected: int get_id_for_track_at_position(unsigned int head, unsigned int position); std::map> cached_tracks_; - std::unique_ptr update_queue_; }; +/*! + Provides a wrapper that wraps a DiskImage to make it into a Disk, providing caching and, + thereby, an intermediate store for modified tracks so that mutable disk images can either + update on the fly or perform a block update on closure, as appropriate. +*/ template class DiskImageHolder: public DiskImageHolderBase { public: template DiskImageHolder(Ts&&... args) : @@ -90,49 +89,7 @@ template class DiskImageHolder: public DiskImageHolderBase { T disk_image_; }; -template unsigned int DiskImageHolder::get_head_position_count() { - return disk_image_.get_head_position_count(); -} - -template unsigned int DiskImageHolder::get_head_count() { - return disk_image_.get_head_count(); -} - -template bool DiskImageHolder::get_is_read_only() { - return disk_image_.get_is_read_only(); -} - -template void DiskImageHolder::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track) { - if(disk_image_.get_is_read_only()) return; - - int address = get_id_for_track_at_position(head, position); - cached_tracks_[address] = track; - - if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue); - std::shared_ptr track_copy(track->clone()); - update_queue_->enqueue([this, head, position, track_copy] { - disk_image_.set_track_at_position(head, position, track_copy); - }); -} - -template std::shared_ptr DiskImageHolder::get_track_at_position(unsigned int head, unsigned int position) { - if(head >= get_head_count()) return nullptr; - if(position >= get_head_position_count()) return nullptr; - - int address = get_id_for_track_at_position(head, position); - std::map>::iterator cached_track = cached_tracks_.find(address); - if(cached_track != cached_tracks_.end()) return cached_track->second; - - std::shared_ptr track = disk_image_.get_track_at_position(head, position); - if(!track) return nullptr; - cached_tracks_[address] = track; - return track; -} - -template DiskImageHolder::~DiskImageHolder() { - if(update_queue_) update_queue_->flush(); -} - +#include "DiskImageImplementation.hpp" } } diff --git a/Storage/Disk/DiskImage/DiskImageImplementation.hpp b/Storage/Disk/DiskImage/DiskImageImplementation.hpp new file mode 100644 index 000000000..e099e9777 --- /dev/null +++ b/Storage/Disk/DiskImage/DiskImageImplementation.hpp @@ -0,0 +1,50 @@ +// +// DiskImageImplementation.hpp +// Clock Signal +// +// Created by Thomas Harte on 22/09/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +template unsigned int DiskImageHolder::get_head_position_count() { + return disk_image_.get_head_position_count(); +} + +template unsigned int DiskImageHolder::get_head_count() { + return disk_image_.get_head_count(); +} + +template bool DiskImageHolder::get_is_read_only() { + return disk_image_.get_is_read_only(); +} + +template void DiskImageHolder::set_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr &track) { + if(disk_image_.get_is_read_only()) return; + + int address = get_id_for_track_at_position(head, position); + cached_tracks_[address] = track; + + if(!update_queue_) update_queue_.reset(new Concurrency::AsyncTaskQueue); + std::shared_ptr track_copy(track->clone()); + update_queue_->enqueue([this, head, position, track_copy] { + disk_image_.set_track_at_position(head, position, track_copy); + }); +} + +template std::shared_ptr DiskImageHolder::get_track_at_position(unsigned int head, unsigned int position) { + if(head >= get_head_count()) return nullptr; + if(position >= get_head_position_count()) return nullptr; + + int address = get_id_for_track_at_position(head, position); + std::map>::iterator cached_track = cached_tracks_.find(address); + if(cached_track != cached_tracks_.end()) return cached_track->second; + + std::shared_ptr track = disk_image_.get_track_at_position(head, position); + if(!track) return nullptr; + cached_tracks_[address] = track; + return track; +} + +template DiskImageHolder::~DiskImageHolder() { + if(update_queue_) update_queue_->flush(); +}