How do I let multi threads access to the Critical Section as reading thread at the same time?

Hi I’m currently learning about SDL mutex.
I learned I need to lock process when thread is reading and another one is writing at the same time and also, writing and writing at the same time
But, I think I don’t need to lock while reading and reading

I do this when thread is either reading or writing.

SDL_LockMutex(lock);
//SomeCriticalSection
SDL_UnlockMutex(lock);

But, though this method, other threads can’t access to CriticalSection as read
while another thread is reading.

What do I do for this?
Are there any methods like Lockmutex as read?
I don’t understand Semaphore and Cond sorry.

You want to use SDL3 with read-write locks:
libsdl-org/SDL: Simple Directmedia Layer (github.com)
SDL3/SDL_CreateRWLock - SDL Wiki (libsdl.org)

1 Like

so it’s not avaiable for now…?
Alright, thank you

You could have one mutex for reading and one for writing.
While reading, lock the reading mutex.
While writing, lock the reading mutex then the writing mutex.
Pretty standard pattern, actually.

@ulatekh How does that allow multiple readers?

It doesn’t.

But we did have to solve this problem for SDL3!

SDL3 will use the OS-provided rwlocks if available (pthread_rwlock_t on many platforms, SRWLOCK on Windows, etc). But for platforms that don’t offer a rwlock, we have a fallback built out of other less-complex synchronization primitives that the platform might have.

This is what SDL3 does, at the time of this writing, if it has to implement its own rwlocks, and this code could be backported to an SDL2 app if necessary, since it only needs public SDL APIs for SDL_mutex and SDL_cond (and, incorrectly, SDL_atomic_t; mutexes are a full memory barrier, so this was unnecessary as a mutex is always held when touching those variables).

The idea is this:

When locking the rwlock for reading:

  • Grab the real mutex,
  • Increment a counter,
  • Release the mutex.

When the reader is unlocking the rwlock:

  • Grab the mutex again,
  • Broadcast to the condition variable,
  • Release the mutex.

So if you have nothing but readers, they all can hold the rwlock in parallel, holding the actual lock only long enough to set a single variable and signal a condition.

Locking for writing, on the other hand:

  • Grab the mutex.
  • If there are any readers holding the rwlock, wait for the condition variable to signal, then check again until there are no readers.
  • Do not release the actual mutex.

When a writer releases a rwlock:

  • Let go of the actual mutex.

The end result of this is that when writing, you have an exclusive lock (which is what a mutex is), and when reading, you just note that you’re in there and otherwise hold no actual lock, so all reading threads can run in parallel.

The implementation is pretty simple, but to be clear, this hasn’t gotten a lot of testing, so if the idea isn’t sound, I’d love to hear feedback!

1 Like

I should learn not to try to answer questions when I’m tired. :upside_down_face:

1 Like

Interesting. I take it that the reader decrements the counter before broadcasting. Seems like it should work.

It does decrement on unlock, I forgot to mention that.

The writer lock also increments/decrements a separate counter, even though there can only be one writer at a time, but the counter allows writer locks to be recursive.