## Thread Safety

Prism provides the following thread safety guarantees:

* The functions `prism_init` and `prism_shutdown` are thread-safe. Multiple threads MAY call `prism_init` concurrently; each call returns an independent context. However, `prism_shutdown` MUST only be called once per context, and the context MUST NOT be used from any thread after `prism_shutdown` has been called on that context. If one thread calls `prism_shutdown` while another thread is using the same context, the behavior is undefined.
* All `prism_registry_*` functions are thread-safe when called on the same context from multiple threads. The registry uses internal reader-writer synchronization to protect its data structures. Read operations (such as `prism_registry_count`, `prism_registry_name`, `prism_registry_exists`, and `prism_registry_priority`) may execute concurrently with each other. Write operations (such as `prism_registry_acquire` and `prism_registry_acquire_best`, which may update internal caches) acquire exclusive access and are serialized with respect to all other operations.
* Individual backend instances are NOT thread-safe. Applications MUST NOT call functions on the same `PrismBackend` instance from multiple threads concurrently without external synchronization. This restriction applies even to logically independent operations; for example, calling `prism_backend_get_rate` from one thread while another thread calls `prism_backend_set_volume` on the same backend instance produces undefined behavior.
* Different backend instances MAY be used from different threads concurrently without restriction. For example, if an application creates two backends using `prism_registry_create`, those two backends may be used from separate threads without synchronization.
* The `prism_registry_create`, `prism_registry_create_best`, `prism_registry_acquire`, and `prism_registry_acquire_best` functions are thread-safe with respect to the registry. However, the returned backend instances are subject to the single-threaded constraint described above.
* Audio callbacks passed to `prism_backend_speak_to_memory` MAY be invoked from a thread other than the calling thread, depending on the backend. Callback implementations MUST be prepared for this possibility and MUST provide their own synchronization if they access shared state. The callback MUST NOT call any Prism function on the backend instance that initiated the synthesis, as this would violate the single-threaded backend constraint and may also cause deadlocks.
* When using `prism_registry_acquire` or `prism_registry_acquire_best`, multiple calls may return handles to the same underlying backend instance if a cached instance exists. In this case, all handles share the same backend state, and the single-threaded constraint applies across all handles. Applications that acquire backends from the cache and use them from multiple threads MUST synchronize access externally.

Applications requiring concurrent speech synthesis from multiple threads SHOULD create separate backend instances per thread using `prism_registry_create` or `prism_registry_create_best`.
