Thread-safe wrapper for Fory using instance pooling. ThreadSafeFory maintains a pool of Fory instances protected by a lock to enable safe concurrent serialization/deserialization across multiple threads. When a thread needs to serialize or deserialize data, it acquires an instance
| 592 | |
| 593 | |
| 594 | class ThreadSafeFory: |
| 595 | """ |
| 596 | Thread-safe wrapper for Fory using instance pooling. |
| 597 | |
| 598 | ThreadSafeFory maintains a pool of Fory instances protected by a lock to enable |
| 599 | safe concurrent serialization/deserialization across multiple threads. When a thread |
| 600 | needs to serialize or deserialize data, it acquires an instance from the pool, uses it, |
| 601 | and returns it for reuse by other threads. |
| 602 | |
| 603 | All type registrations must be performed before any serialization operations to ensure |
| 604 | consistency across all pooled instances. Attempting to register types after the first |
| 605 | serialization will raise a RuntimeError. |
| 606 | |
| 607 | Args: |
| 608 | xlang (bool): Whether to enable xlang mode. Defaults to True. |
| 609 | ref (bool): Whether to enable reference tracking. Defaults to False. |
| 610 | strict (bool): Whether to require type registration. Defaults to True. |
| 611 | compatible (bool): Whether to enable compatible mode. Defaults to compatible mode |
| 612 | in both xlang and Python native mode. Set False only when every reader and |
| 613 | writer always uses the same Python class schema and smaller payloads matter. |
| 614 | max_depth (int): Maximum depth for deserialization. Defaults to 50. |
| 615 | Example: |
| 616 | >>> import pyfory |
| 617 | >>> import threading |
| 618 | >>> from dataclasses import dataclass |
| 619 | >>> |
| 620 | >>> @dataclass |
| 621 | >>> class Person: |
| 622 | ... name: str |
| 623 | ... age: int |
| 624 | >>> |
| 625 | >>> # Create thread-safe instance |
| 626 | >>> fory = pyfory.ThreadSafeFory(xlang=False) |
| 627 | >>> fory.register(Person) |
| 628 | >>> |
| 629 | >>> # Use safely from multiple threads |
| 630 | >>> def worker(thread_id): |
| 631 | ... person = Person(f"User{thread_id}", 25) |
| 632 | ... data = fory.serialize(person) |
| 633 | ... result = fory.deserialize(data) |
| 634 | ... print(f"Thread {thread_id}: {result}") |
| 635 | >>> |
| 636 | >>> threads = [threading.Thread(target=worker, args=(i,)) for i in range(5)] |
| 637 | >>> for t in threads: t.start() |
| 638 | >>> for t in threads: t.join() |
| 639 | |
| 640 | Note: |
| 641 | - Register all types before calling serialize/deserialize |
| 642 | - The pool grows dynamically as needed based on thread contention |
| 643 | - Instances are automatically returned to the pool after use |
| 644 | - Both Python and Cython modes are supported automatically |
| 645 | """ |
| 646 | |
| 647 | def __init__(self, fory_factory=None, **kwargs): |
| 648 | import threading |
| 649 | |
| 650 | self._config = kwargs |
| 651 | self._fory_factory = fory_factory |
no outgoing calls