| LICENSE | ||
| module.jai | ||
| README.md | ||
🔒 A shared/exclusive or read/write lock module for Jai
A very lean implementation of a user-space shared/exclusive (aka. read/write) lock for the Jai programming language. You can check the code in module.jai.
How To
The most recommended way is to call with_shared_lock and with_exclusive_lock which will automatically lock and defer an unlock for the end of the current scope.
You can declare a lock simply by instantiating a Spin_Shared_Exclusive_Lock, its default value already initializes the lock as not held.
my_lock : Spin_Shared_Exclusive_Lock;
Then to get a shared lock you can call with_shared_lock. With this type of lock any threads with shared access will be allowed access at the same time, meaning that there can be multiple people with a concurrent shared lock.
{
with_shared_lock(*my_lock);
// . . . use the resource with shared access in this scope . . .
}
And similarly, to get an exclusive lock you'd call with_exclusive_lock. An exclusive lock will give access to only one thread. This means that no other shared nor exclusive accesses will be allowed.
{
with_exclusive_lock(*my_lock);
// . . . use the resource with exclusive access in this scope . . .
}
So essentially the lock can be in one of three states:
- Not Grabbed: Nobody has the lock, any thread can get either a shared or an exclusive lock right now.
- Grabbed with shared access: Potentially by any number of threads all with shared access. Any other thread can grab shared access, but any wanting exclusive access would need to wait for all the shared accesses to be unlocked.
- Grabbed with exclusive access: A single thread has exclusive access, no other threads can grab any other accesses until the current one unlocks.
Notes
Recursion
Often other implementations don't allow any kind of recursion, not shared->shared, exclusive->exclusive or exclusive->shared. This is the case for Posix's pthread_rwlock or Windows' SRWLocks. However this lock allows for recursive grabs, that is, grabbing a lock after you already have it is fine and handled properly through the macros.
There is one exception to this which is the shared->exclusive case, the case where you have a shared/read lock and you try to recursively grab an exclusive/write lock. In this case we can't tell that the current thread already has the lock so the current thread would forever wait for itself.
{
with_shared_lock(*my_lock);
with_exclusive_lock(*my_lock); // This will spin forever! It can't know the current thread
}
So do recursion if you need it but make sure that you never try to upgrade a shared lock to an exclusive one recursively. It's generally a good idea not to mess with recursion with locks if you can avoid it though 😁.
License
I want people to be able to just use this without thinking about licensing, although give me a shout if you do use it and attribution is appreciated 😊. Replicating STB's (https://github.com/nothings/stb) licensing stuff where you can choose to use public domain or MIT.