3rdparty/libchdr: Allow cancelling precache

This commit is contained in:
Stenzek 2024-06-10 02:27:12 +10:00 committed by Connor McLaughlin
parent d43171454b
commit 8a3513f2ba
2 changed files with 15 additions and 16 deletions

View File

@ -291,7 +291,8 @@ enum _chd_error
CHDERR_INVALID_STATE, CHDERR_INVALID_STATE,
CHDERR_OPERATION_PENDING, CHDERR_OPERATION_PENDING,
CHDERR_NO_ASYNC_OPERATION, CHDERR_NO_ASYNC_OPERATION,
CHDERR_UNSUPPORTED_FORMAT CHDERR_UNSUPPORTED_FORMAT,
CHDERR_CANCELLED,
}; };
typedef enum _chd_error chd_error; typedef enum _chd_error chd_error;
@ -383,7 +384,7 @@ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent,
/* precache underlying file */ /* precache underlying file */
CHD_EXPORT chd_error chd_precache(chd_file *chd); CHD_EXPORT chd_error chd_precache(chd_file *chd);
CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t pos, size_t total, void* param), void* param); CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, bool(*progress)(size_t pos, size_t total, void* param), void* param);
/* close a CHD file */ /* close a CHD file */
CHD_EXPORT void chd_close(chd_file *chd); CHD_EXPORT void chd_close(chd_file *chd);

View File

@ -1962,16 +1962,13 @@ CHD_EXPORT chd_error chd_precache(chd_file* chd)
return chd_precache_progress(chd, NULL, NULL); return chd_precache_progress(chd, NULL, NULL);
} }
CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t pos, size_t total, void* param), void* param) CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, bool(*progress)(size_t pos, size_t total, void* param), void* param)
{ {
#define PRECACHE_CHUNK_SIZE 16 * 1024 * 1024 #define PRECACHE_CHUNK_SIZE 16 * 1024 * 1024
size_t count;
UINT64 size, done, req_count, last_update_done, update_interval;
if (chd->file_cache == NULL) if (chd->file_cache == NULL)
{ {
size = core_fsize(chd->file); const UINT64 size = core_fsize(chd->file);
if ((INT64)size <= 0) if ((INT64)size <= 0)
return CHDERR_INVALID_DATA; return CHDERR_INVALID_DATA;
@ -1983,17 +1980,14 @@ CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t
return CHDERR_OUT_OF_MEMORY; return CHDERR_OUT_OF_MEMORY;
core_fseek(chd->file, 0, SEEK_SET); core_fseek(chd->file, 0, SEEK_SET);
done = 0; UINT64 done = 0;
last_update_done = 0;
update_interval = ((size + 99) / 100);
while (done < size) while (done < size)
{ {
req_count = size - done; UINT64 req_count = size - done;
if (req_count > PRECACHE_CHUNK_SIZE) if (req_count > PRECACHE_CHUNK_SIZE)
req_count = PRECACHE_CHUNK_SIZE; req_count = PRECACHE_CHUNK_SIZE;
count = core_fread(chd->file, chd->file_cache + (size_t)done, (size_t)req_count); size_t count = core_fread(chd->file, chd->file_cache + (size_t)done, (size_t)req_count);
if (count != (size_t)req_count) if (count != (size_t)req_count)
{ {
free(chd->file_cache); free(chd->file_cache);
@ -2002,10 +1996,14 @@ CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, void(*progress)(size_t
} }
done += req_count; done += req_count;
if (progress != NULL && (done - last_update_done) >= update_interval && done != size) if (progress != NULL)
{ {
last_update_done = done; if (!progress(done, size, param))
progress(done, size, param); {
free(chd->file_cache);
chd->file_cache = NULL;
return CHDERR_CANCELLED;
}
} }
} }
} }