uCalc API Version: 2.1.3-preview.2 Released: 6/17/2026
Warning
uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.
Thread safety
Product:
Class:
Explains uCalc's thread safety model and the best practices for using the library in multi-threaded applications.
Remarks
🧵 Thread Safety in uCalc
This guide covers the principles and best practices for using the uCalc library in multi-threaded applications, such as web servers, parallel data processors, or applications with responsive user interfaces.
1. The Core Principle: Instance Isolation
A single uCalc instance is not thread-safe. An instance is a stateful engine containing variables, functions, error states, and configuration settings. Attempting to access or modify a single instance from multiple threads concurrently without external locking will lead to race conditions, corrupted state, and unpredictable behavior.
Do not share a single uCalc instance across multiple threads.
2. ✅ The Recommended Solution: One Instance Per Thread
The correct and most performant approach is to provide each thread with its own dedicated uCalc instance. The recommended pattern is to:
- Create a Master Instance: Configure a single, master
uCalcobject with all the required functions, operators, variables, and settings during your application's startup phase. - Clone for Each Thread: When a new thread or task begins, create a local copy for that thread by calling Clone() on the master instance. Cloning is a highly optimized operation designed for this exact purpose.
- Use and Release: The thread performs its work using its private clone. When the work is complete, the cloned instance should be released.
This pattern ensures complete thread isolation, allowing for maximum parallelism without any risk of state corruption.
3. ✨ The Exception: The Thread-Local Default Instance
A key architectural feature of uCalc is that the default instance stack is thread-local. The static DefaultInstance property does not return a single global object; it returns the default instance for the currently executing thread.
This means:
- If Thread A calls myInstance.IsDefault(true), it only affects the default instance for Thread A.
- Thread B's default instance remains completely unaffected.
This makes the default instance mechanism surprisingly robust and safe for use in multi-threaded environments, allowing different components or threads to work with their own ambient contexts without conflict.
4. ❌ The Anti-Pattern: External Locking
A developer's first instinct might be to wrap all calls to a shared uCalc instance in a lock or mutex. While this would prevent race conditions, it is strongly discouraged as an anti-pattern.
// ANTI-PATTERN: Do not do this!lock (sharedCalc) { result = sharedCalc.Eval("...");}Using locks serializes access to the uCalc engine, creating a major performance bottleneck that completely negates the benefits of multi-threading. The 'one instance per thread' model allows for true parallel execution and is significantly more scalable.
💡 Why uCalc? (Comparative Analysis)
- Instance-Based vs. Static: Many simpler libraries provide only static evaluation functions, making them unsuitable for multi-threading due to shared global state. uCalc's instance-based design provides natural encapsulation, making it a perfect fit for parallel processing.
- Efficient Cloning: The Clone() method is lightweight and optimized. It avoids the high cost of creating a new instance and re-running dozens of
Definecalls from scratch for every thread. - Built-in Thread-Local Default: The thread-safe default instance is a sophisticated feature that simplifies working with ambient contexts in multi-threaded code, a task that would otherwise require manual implementation of thread-local storage patterns.