Crates.io | per-thread-mutex |
lib.rs | per-thread-mutex |
version | 0.1.3 |
source | src |
created_at | 2023-08-25 19:36:48.309344 |
updated_at | 2024-08-21 18:54:39.242369 |
description | Synchronization lock designed for wrapping thread-unsafe C libraries |
homepage | https://github.com/jbaublitz/per-thread-mutex |
repository | https://github.com/jbaublitz/per-thread-mutex |
max_upload_size | |
id | 954995 |
size | 30,873 |
Synchronization lock intended for thread unsafe C libraries.
When working with certain C libraries, concurrent accesses are not safe. It can be problematic to model this at the Rust level largely because language level support can't enforce everything that's necessary to maintain safety in all cases.
Send
/Sync
can ensure that data structures are not used and sent across
threads which provides part of the puzzle. However for certain cases thread-unsafe libraries
can be used in a multithreaded context provided two conditions are upheld.
Send
/Sync
.This crate aims to address requirement 2.
The intended use of this mutex is with lazy_static
as a global variable in Rust bindings for
thread-unsafe C code. The mutex should be locked before each call into the library. This
ensures that there are never any concurrent accesses from separate threads which could lead to
unsafe behavior.
The lock keeps track of two pieces of data: the thread ID of the thread that currently has the lock acquisition and the number of acquisitions currently active on the lock. Acquisitions from the same thread ID are allowed at the same time and the lock available once all acquisitions of the lock are released.
This largely stems from C's heavy use of callbacks. If a callback is built into a C API, it is typical in Rust bindings to write the callback in Rust and to write a C shim to convert from C to Rust data types. Consider the case of an API call that, in its implementation, calls a callback where the callback also calls a Rust-wrapped API call. This is a safe usage of the library, but would result in a double acquisition of a traditional mutex guarding calls into the library. This lock allows both of those acquisitions to succeed without blocking, preventing the deadlock that would be caused by a traditional mutex while still guard against unsafe accesses of the library.