diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-09 10:41:33 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-10 09:17:07 -0300 |
| commit | 9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a (patch) | |
| tree | 91fce278abc85e4f7491de8b5f02184c8a2d5a56 /src/pdf_bridge.c | |
| parent | 2b1fac6fecbf7d7cc08f9dad24687b05e9968c9a (diff) | |
| download | pardes-9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a.tar.gz pardes-9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a.zip | |
replace ArrayLists with bounded storage
Diffstat (limited to 'src/pdf_bridge.c')
| -rw-r--r-- | src/pdf_bridge.c | 112 |
1 files changed, 107 insertions, 5 deletions
diff --git a/src/pdf_bridge.c b/src/pdf_bridge.c index e0969018..25870f20 100644 --- a/src/pdf_bridge.c +++ b/src/pdf_bridge.c @@ -5,12 +5,17 @@ #include <math.h> #include <limits.h> #include <stdint.h> +#include <stdatomic.h> #include <stdlib.h> #include <string.h> #define PARDES_PDF_INITIAL_RESULT_QUADS 64 struct pardes_pdf_document { + pardes_pdf_allocator allocator; + fz_alloc_context mupdf_allocator; + int uses_allocator; + fz_context *ctx; fz_document *doc; int page_count; @@ -26,6 +31,97 @@ struct pardes_pdf_document { int display_list_candidate_page_number; }; +static pardes_pdf_allocator pardes_pdf_global_allocator; +static int pardes_pdf_allocator_installed; +static _Atomic size_t pardes_pdf_active_documents; +static atomic_flag pardes_pdf_allocator_lock = ATOMIC_FLAG_INIT; + +static void +pardes_pdf_lock_allocator(void) +{ + while (atomic_flag_test_and_set_explicit( + &pardes_pdf_allocator_lock, memory_order_acquire)) + ; +} + +static void +pardes_pdf_unlock_allocator(void) +{ + atomic_flag_clear_explicit( + &pardes_pdf_allocator_lock, memory_order_release); +} + + +int +pardes_pdf_set_allocator(const pardes_pdf_allocator *allocator) +{ + int status = PARDES_PDF_OK; + + if (allocator != NULL && + (allocator->alloc == NULL || allocator->realloc == NULL || + allocator->free == NULL)) + return PARDES_PDF_ERROR; + + pardes_pdf_lock_allocator(); + if (atomic_load(&pardes_pdf_active_documents) != 0) { + status = PARDES_PDF_ERROR; + } else if (allocator == NULL) { + memset(&pardes_pdf_global_allocator, 0, + sizeof(pardes_pdf_global_allocator)); + pardes_pdf_allocator_installed = 0; + } else { + pardes_pdf_global_allocator = *allocator; + pardes_pdf_allocator_installed = 1; + } + pardes_pdf_unlock_allocator(); + return status; +} + +static pardes_pdf_document * +pardes_pdf_allocate_document(void) +{ + pardes_pdf_document *document; + pardes_pdf_allocator allocator; + int uses_allocator; + + pardes_pdf_lock_allocator(); + uses_allocator = pardes_pdf_allocator_installed; + allocator = pardes_pdf_global_allocator; + atomic_fetch_add(&pardes_pdf_active_documents, 1); + pardes_pdf_unlock_allocator(); + + if (uses_allocator) { + document = (pardes_pdf_document *)allocator.alloc( + allocator.user, sizeof(*document)); + } else { + document = (pardes_pdf_document *)calloc(1, sizeof(*document)); + } + if (document == NULL) { + atomic_fetch_sub(&pardes_pdf_active_documents, 1); + return NULL; + } + if (!uses_allocator) + return document; + + memset(document, 0, sizeof(*document)); + document->allocator = allocator; + document->uses_allocator = 1; + document->mupdf_allocator.user = allocator.user; + document->mupdf_allocator.malloc = allocator.alloc; + document->mupdf_allocator.realloc = allocator.realloc; + document->mupdf_allocator.free = allocator.free; + return document; +} + +static void +pardes_pdf_free_document(pardes_pdf_document *document) +{ + if (document->uses_allocator) + document->allocator.free(document->allocator.user, document); + else + free(document); +} + static void pardes_pdf_drop_cached_page(pardes_pdf_document *document) { @@ -230,15 +326,19 @@ pardes_pdf_open(const char *path, int *page_count) if (path == NULL || page_count == NULL) return NULL; - state = (pardes_pdf_document *)calloc(1, sizeof(*state)); + state = pardes_pdf_allocate_document(); if (state == NULL) return NULL; state->cached_page_number = -1; state->display_list_candidate_page_number = -1; - ctx = fz_new_context(NULL, NULL, PARDES_PDF_STORE_LIMIT_BYTES); + ctx = fz_new_context( + state->uses_allocator ? &state->mupdf_allocator : NULL, + NULL, + PARDES_PDF_STORE_LIMIT_BYTES); if (ctx == NULL) { - free(state); + pardes_pdf_free_document(state); + atomic_fetch_sub(&pardes_pdf_active_documents, 1); return NULL; } @@ -256,7 +356,8 @@ pardes_pdf_open(const char *path, int *page_count) fz_report_error(ctx); fz_drop_document(ctx, doc); fz_drop_context(ctx); - free(state); + pardes_pdf_free_document(state); + atomic_fetch_sub(&pardes_pdf_active_documents, 1); return NULL; } @@ -275,7 +376,8 @@ pardes_pdf_close(pardes_pdf_document *document) pardes_pdf_drop_cached_page(document); fz_drop_document(document->ctx, document->doc); fz_drop_context(document->ctx); - free(document); + pardes_pdf_free_document(document); + atomic_fetch_sub(&pardes_pdf_active_documents, 1); } int |
