SID Input: Bring back file hints, better this time

Now file hint stashes the whole file in memory, so that any other
threads reading the file at the same time will just grab the same memory
block and read it, rather than opening the file repeatedly.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CQTexperiment
Christopher Snowhill 2022-02-11 04:43:20 -08:00
parent 425306129f
commit e695e33537
2 changed files with 144 additions and 10 deletions

View File

@ -23,6 +23,7 @@
sidplayfp *engine;
sidbuilder *builder;
id<CogSource> source;
long length;
NSString *currentUrl;
@ -35,5 +36,7 @@
long fadeRemain;
}
- (void)setSource:(id<CogSource>)s;
- (id<CogSource>)source;
- (void)cleanUp;
@end

View File

@ -21,7 +21,116 @@
static const char *extListEmpty[] = { NULL };
static const char *extListStr[] = { ".str", NULL };
@interface sid_file_object : NSObject {
size_t refCount;
NSString *path;
NSData *data;
}
@property size_t refCount;
@property NSString *path;
@property NSData *data;
@end
@implementation sid_file_object
@synthesize refCount;
@synthesize path;
@synthesize data;
@end
@interface sid_file_container : NSObject {
NSLock *lock;
NSMutableDictionary *list;
}
+ (sid_file_container *)instance;
- (void)add_hint:(NSString *)path source:(id)source;
- (void)remove_hint:(NSString *)path;
- (BOOL)try_hint:(NSString *)path data:(NSData **)data;
@end
@implementation sid_file_container
+ (sid_file_container *)instance {
static sid_file_container *instance;
@synchronized(self) {
if(!instance) {
instance = [[self alloc] init];
}
}
return instance;
}
- (sid_file_container *)init {
if((self = [super init])) {
lock = [[NSLock alloc] init];
list = [[NSMutableDictionary alloc] initWithCapacity:0];
}
return self;
}
- (void)add_hint:(NSString *)path source:(id)source {
[lock lock];
sid_file_object *obj = [list objectForKey:path];
if(obj) {
obj.refCount += 1;
[lock unlock];
return;
}
[lock unlock];
obj = [[sid_file_object alloc] init];
obj.refCount = 1;
if(![source seekable])
return;
[source seek:0 whence:SEEK_END];
size_t fileSize = [source tell];
void *dataBytes = malloc(fileSize);
if(!dataBytes)
return;
[source seek:0 whence:SEEK_SET];
[source read:dataBytes amount:fileSize];
NSData *data = [NSData dataWithBytes:dataBytes length:fileSize];
free(dataBytes);
obj.path = path;
obj.data = data;
[lock lock];
[list setObject:obj forKey:path];
[lock unlock];
}
- (void)remove_hint:(NSString *)path {
[lock lock];
sid_file_object *obj = [list objectForKey:path];
if(obj.refCount <= 1) {
[list removeObjectForKey:path];
} else {
obj.refCount--;
}
[lock unlock];
}
- (BOOL)try_hint:(NSString *)path data:(NSData **)data {
sid_file_object *obj;
[lock lock];
obj = [list objectForKey:path];
[lock unlock];
if(obj) {
*data = obj.data;
return YES;
} else {
return NO;
}
}
@end
static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef) {
NSData *hintData = nil;
if(![[sid_file_container instance] try_hint:[NSString stringWithUTF8String:fileName] data:&hintData]) {
NSString *urlString = [NSString stringWithUTF8String:fileName];
NSURL *url = [NSURL URLWithDataRepresentation:[urlString dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil];
@ -35,14 +144,18 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
return;
[source seek:0 whence:SEEK_END];
long size = [source tell];
long fileSize = [source tell];
[source seek:0 whence:SEEK_SET];
bufferRef.resize(size);
bufferRef.resize(fileSize);
[source read:&bufferRef[0] amount:size];
[source read:&bufferRef[0] amount:fileSize];
[source close];
} else {
bufferRef.resize([hintData length]);
memcpy(&bufferRef[0], [hintData bytes], [hintData length]);
}
}
@implementation SidDecoder
@ -51,6 +164,8 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
if(![s seekable])
return NO;
[self setSource:s];
NSString *path = [[s url] absoluteString];
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
if(fragmentRange.location != NSNotFound) {
@ -59,6 +174,9 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
currentUrl = [path stringByRemovingPercentEncoding];
[[sid_file_container instance] add_hint:currentUrl source:s];
hintAdded = YES;
NSString *extension = [[s url] pathExtension];
const char **extList = [extension isEqualToString:@"mus"] ? extListStr : extListEmpty;
@ -253,6 +371,11 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
tune = NULL;
}
source = nil;
if(hintAdded) {
[[sid_file_container instance] remove_hint:currentUrl];
hintAdded = NO;
}
currentUrl = nil;
}
@ -264,6 +387,14 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
[self close];
}
- (void)setSource:(id<CogSource>)s {
source = s;
}
- (id<CogSource>)source {
return source;
}
+ (NSArray *)fileTypes {
return @[@"sid", @"mus"];
}