Context and memory

Read side by side

On this page

A context owns execution policy that is not part of an individual number:

Explicit contexts are intended to be owned by one thread. The convenience default context is thread-local, including its flags and scratch arena.

Custom allocators

ppf_context_init_custom accepts malloc, realloc, and free callbacks plus an opaque pointer. Objects initialized through a context retain the allocator callbacks needed to release their own significand storage. The opaque allocator state must remain valid until every dependent object and context has been cleared.

Version 0.10.9 adds PPF_FLAG_ALLOC. Context-owned allocation helpers raise this sticky flag when a configured allocator rejects a request.

Transactional failures

The deterministic 0.10.9 hardening suite verifies that covered operations leave an already initialized destination byte-for-byte unchanged when an allocation failure cannot be recovered. It also verifies successful cleanup and reuse.

ppf_init2_ctx accepts a mutable context because initialization can now raise the allocation flag. An initialization failure leaves an all-zero object that can safely be cleared.

ppf_reserve and ppf_set_prec preserve the object when reallocation fails. Their existing signatures do not accept a context, so they do not raise a caller-selected context flag.

Scratch arena

The scratch arena uses stable linked blocks. Growing the arena does not invalidate pointers returned from earlier blocks. A mark can be restored after a temporary calculation, and a reset keeps the first block for reuse.

Version 0.11.0 aligns arena metadata explicitly inside the original allocator block and retains the original pointer and exact size for deallocation. This makes the metadata valid even when a sanitizer or custom allocator returns a pointer with less alignment than the internal block type requires. Returned scratch addresses continue to honor the caller's power-of-two alignment.

When arena growth fails, the old block chain and active mark remain valid. The allocation flag is raised and the request returns null.

See ALLOCATION_FAILURE_CONTRACT.md for the exact covered operations and the remaining boundary.

Thread lifecycle

The default context is thread-local. Version 0.11.0 registers a POSIX thread-specific destructor on first use of heap-backed thread state. Normal thread exit releases the default-context arena and thread-local product workspaces when the key could be registered.

ppf_thread_cleanup() provides deterministic cleanup and may be called more than once. Applications should use it before unloading the library and on the main thread when leak-clean shutdown evidence is required. User-owned numbers, explicit contexts, divisor plans, and random states are never destroyed automatically.

Explicit contexts are mutable and should have one-thread-at-a-time ownership. Read-only numbers and completed divisor plans may be shared under the ownership rules in THREAD_SAFETY.md.