mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-21 04:29:34 +00:00
Attempted to switch to an asynchronous means for continuous file updates. Testing with SSD, as usual.
This commit is contained in:
parent
bbd94749f4
commit
6fc692cd34
@ -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);
|
int address = get_id_for_track_at_position(head, position);
|
||||||
cached_tracks_[address] = track;
|
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<Track> Disk::get_track_at_position(unsigned int head, unsigned int position)
|
std::shared_ptr<Track> Disk::get_track_at_position(unsigned int head, unsigned int position)
|
||||||
@ -30,21 +34,15 @@ std::shared_ptr<Track> Disk::get_track_at_position(unsigned int head, unsigned i
|
|||||||
std::map<int, std::shared_ptr<Track>>::iterator cached_track = cached_tracks_.find(address);
|
std::map<int, std::shared_ptr<Track>>::iterator cached_track = cached_tracks_.find(address);
|
||||||
if(cached_track != cached_tracks_.end()) return cached_track->second;
|
if(cached_track != cached_tracks_.end()) return cached_track->second;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock_guard(file_access_mutex_);
|
||||||
std::shared_ptr<Track> track = get_uncached_track_at_position(head, position);
|
std::shared_ptr<Track> track = get_uncached_track_at_position(head, position);
|
||||||
cached_tracks_[address] = track;
|
cached_tracks_[address] = track;
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Track> Disk::get_modified_track_at_position(unsigned int head, unsigned int position)
|
void Disk::store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track, std::mutex &file_access_mutex) {}
|
||||||
{
|
|
||||||
int address = get_id_for_track_at_position(head, position);
|
|
||||||
if(modified_tracks_.find(address) == modified_tracks_.end()) return nullptr;
|
|
||||||
std::map<int, std::shared_ptr<Track>>::iterator cached_track = cached_tracks_.find(address);
|
|
||||||
if(cached_track == cached_tracks_.end()) return nullptr;
|
|
||||||
return cached_track->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Disk::get_is_modified()
|
void Disk::flush_updates()
|
||||||
{
|
{
|
||||||
return !modified_tracks_.empty();
|
if(update_queue_) update_queue_->flush();
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
#ifndef Disk_hpp
|
#ifndef Disk_hpp
|
||||||
#define Disk_hpp
|
#define Disk_hpp
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "../Storage.hpp"
|
#include "../Storage.hpp"
|
||||||
|
#include "../../Concurrency/AsyncTaskQueue.hpp"
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
namespace Disk {
|
namespace Disk {
|
||||||
@ -107,20 +110,15 @@ class Disk {
|
|||||||
*/
|
*/
|
||||||
virtual std::shared_ptr<Track> get_uncached_track_at_position(unsigned int head, unsigned int position) = 0;
|
virtual std::shared_ptr<Track> 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();
|
|
||||||
|
|
||||||
/*!
|
virtual void store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track, std::mutex &file_access_mutex);
|
||||||
@returns the @c Track at @c position underneath @c head if a modification was written there.
|
void flush_updates();
|
||||||
*/
|
|
||||||
std::shared_ptr<Track> get_modified_track_at_position(unsigned int head, unsigned int position);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<int, std::shared_ptr<Track>> cached_tracks_;
|
std::map<int, std::shared_ptr<Track>> cached_tracks_;
|
||||||
std::set<int> modified_tracks_;
|
|
||||||
int get_id_for_track_at_position(unsigned int head, unsigned int position);
|
int get_id_for_track_at_position(unsigned int head, unsigned int position);
|
||||||
|
std::mutex file_access_mutex_;
|
||||||
|
std::unique_ptr<Concurrency::AsyncTaskQueue> update_queue_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,25 +39,26 @@ AcornADF::AcornADF(const char *file_name) :
|
|||||||
|
|
||||||
AcornADF::~AcornADF()
|
AcornADF::~AcornADF()
|
||||||
{
|
{
|
||||||
if(get_is_modified())
|
flush_updates();
|
||||||
{
|
// if(get_is_modified())
|
||||||
for(unsigned int head = 0; head < get_head_count(); head++)
|
// {
|
||||||
{
|
// for(unsigned int head = 0; head < get_head_count(); head++)
|
||||||
for(unsigned int track = 0; track < get_head_position_count(); track++)
|
// {
|
||||||
{
|
// for(unsigned int track = 0; track < get_head_position_count(); track++)
|
||||||
std::shared_ptr<Storage::Disk::Track> modified_track = get_modified_track_at_position(head, track);
|
// {
|
||||||
if(modified_track)
|
// std::shared_ptr<Storage::Disk::Track> 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++)
|
// Storage::Encodings::MFM::Parser parser(true, modified_track);
|
||||||
{
|
// for(unsigned int c = 0; c < sectors_per_track; c++)
|
||||||
std::shared_ptr<Storage::Encodings::MFM::Sector> sector = parser.get_sector((uint8_t)track, (uint8_t)c);
|
// {
|
||||||
printf("Sector %d: %p\n", c, sector.get());
|
// std::shared_ptr<Storage::Encodings::MFM::Sector> 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()
|
unsigned int AcornADF::get_head_position_count()
|
||||||
|
@ -32,27 +32,10 @@ SSD::SSD(const char *file_name) :
|
|||||||
|
|
||||||
SSD::~SSD()
|
SSD::~SSD()
|
||||||
{
|
{
|
||||||
if(get_is_modified())
|
flush_updates();
|
||||||
{
|
|
||||||
for(unsigned int head = 0; head < head_count_; head++)
|
|
||||||
{
|
|
||||||
for(unsigned int track = 0; track < track_count_; track++)
|
|
||||||
{
|
|
||||||
std::shared_ptr<Storage::Disk::Track> 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<Storage::Encodings::MFM::Sector> sector = parser.get_sector((uint8_t)track, (uint8_t)c);
|
|
||||||
printf("Sector %d: %p\n", c, sector.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int SSD::get_head_position_count()
|
unsigned int SSD::get_head_position_count()
|
||||||
{
|
{
|
||||||
return track_count_;
|
return track_count_;
|
||||||
@ -68,13 +51,17 @@ bool SSD::get_is_read_only()
|
|||||||
return 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<Track> SSD::get_uncached_track_at_position(unsigned int head, unsigned int position)
|
std::shared_ptr<Track> SSD::get_uncached_track_at_position(unsigned int head, unsigned int position)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Track> track;
|
std::shared_ptr<Track> track;
|
||||||
|
|
||||||
if(head >= head_count_) return track;
|
if(head >= head_count_) return track;
|
||||||
long file_offset = (position * head_count_ + head) * 256 * 10;
|
fseek(file_, get_file_offset_for_position(head, position), SEEK_SET);
|
||||||
fseek(file_, file_offset, SEEK_SET);
|
|
||||||
|
|
||||||
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
std::vector<Storage::Encodings::MFM::Sector> sectors;
|
||||||
for(int sector = 0; sector < 10; sector++)
|
for(int sector = 0; sector < 10; sector++)
|
||||||
@ -99,3 +86,25 @@ std::shared_ptr<Track> SSD::get_uncached_track_at_position(unsigned int head, un
|
|||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSD::store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track, std::mutex &file_access_mutex)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> parsed_track;
|
||||||
|
Storage::Encodings::MFM::Parser parser(false, track);
|
||||||
|
for(unsigned int c = 0; c < 10; c++)
|
||||||
|
{
|
||||||
|
std::shared_ptr<Storage::Encodings::MFM::Sector> 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<std::mutex> 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_);
|
||||||
|
}
|
||||||
|
@ -39,7 +39,9 @@ class SSD: public Disk, public Storage::FileHolder {
|
|||||||
bool get_is_read_only();
|
bool get_is_read_only();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void store_updated_track_at_position(unsigned int head, unsigned int position, const std::shared_ptr<Track> &track, std::mutex &file_access_mutex);
|
||||||
std::shared_ptr<Track> get_uncached_track_at_position(unsigned int head, unsigned int position);
|
std::shared_ptr<Track> 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 head_count_;
|
||||||
unsigned int track_count_;
|
unsigned int track_count_;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user