Slimreader/writer (SRW) locks enable the threads of a single process to access shared resources; they are optimized for speed and occupy very little memory. Slim reader-writer locks cannot be shared across processes.
Reader threads read data from a shared resource whereas writer threads write data to a shared resource. When multiple threads are reading and writing using a shared resource, exclusive locks such as a critical section or mutex can become a bottleneck if the reader threads run continuously but write operations are rare.
Shared mode, which grants shared read-only access to multiple reader threads, which enables them to read data from the shared resource concurrently. If read operations exceed write operations, this concurrency increases performance and throughput compared to critical sections.
Exclusive mode, which grants read/write access to one writer thread at a time. When the lock has been acquired in exclusive mode, no other thread can access the shared resource until the writer releases the lock.
Exclusive mode SRW locks cannot be acquired recursively. If a thread tries to acquire a lock that it already holds, that attempt will fail (for TryAcquireSRWLockExclusive) or deadlock (for AcquireSRWLockExclusive)
A single SRW lock can be acquired in either mode; reader threads can acquire it in shared mode whereas writer threads can acquire it in exclusive mode. There is no guarantee about the order in which threads that request ownership will be granted ownership; SRW locks are neither fair nor FIFO.
An SRW lock is the size of a pointer. The advantage is that it is fast to update the lock state. The disadvantage is that very little state information can be stored, so SRW locks do not detect incorrect recursive use in shared mode. In addition, a thread that owns an SRW lock in shared mode cannot upgrade its ownership of the lock to exclusive mode.
The caller must allocate an SRWLOCK structure and initialize it by either calling InitializeSRWLock (to initialize the structure dynamically) or assign the constant SRWLOCK_INIT to the structure variable (to initialize the structure statically).
I have to implement a read/write lock in C++ using the Win32 api as part of a project at work. All of the existing solutions use kernel objects (semaphores and mutexes) that require a context switch during execution. This is far too slow for my application.
Joe Duffy's blog has some recent entries on implementing different types of non-blocking reader/writer locks. These locks do spin, so they would not be appropriate if you intend to do a lot of work while holding the lock. The code is C#, but should be straightforward to port to native.
I don't think this can be done without using at least one kernel-level object (Mutex or Semaphore), because you need the help of the kernel to make the calling process block until the lock is available.
Critical sections do provide blocking, but the API is too limited. e.g. you cannot grab a CS, discover that a read lock is available but not a write lock, and wait for the other process to finish reading (because if the other process has the critical section it will block other readers which is wrong, and if it doesn't then your process will not block but spin, burning CPU cycles.)
However what you can do is use a spin lock and fall back to a mutex whenever there is contention. The critical section is itself implemented this way. I would take an existing critical section implementation and replace the PID field with separate reader & writer counts.
Old question, but this is something that should work. It doesn't spin on contention. Readers incur limited extra cost if they have little or no contention, because SetEvent is called lazily (look at the edit history for a more heavyweight version that doesn't have this optimization).
This is an old question but perhaps someone will find this useful. We developed a high-performance, open-source RWLock for Windows that automatically uses Vista+ SRWLock Michael mentioned if available, or otherwise falls back to a userspace implementation.
As an added bonus, there are four different "flavors" of it (though you can stick to the basic, which is also the fastest), each providing more synchronization options. It starts with the basic RWLock() which is non-reentrant, limited to single-process synchronization, and no swapping of read/write locks to a full-fledged cross-process IPC RWLock with re-entrance support and read/write de-elevation.
As mentioned, they dynamically swap out to the Vista+ slim read-write locks for best performance when possible, but you don't have to worry about that at all as it'll fall back to a fully-compatible implementation on Windows XP and its ilk.
We rolled our own using two critical sections and some counters. It suits our needs - we have a very low writer count, writers get precedence over readers, etc. I'm not at liberty to publish ours but can say that it is possible without mutexes and semaphores.
Starting with Windows Vista with Service Pack 1 (SP1), a set of related routines use spin locks to support synchronized access to data structures that are shared by readers and writers. A thread that requires only read access to a data structure can use a spin lock to share this structure with other reader threads. A thread that needs to write to a shared data structure must use the spin lock to obtain exclusive access to the data structure before it can write to this structure.
If a reader thread needs to acquire a spin lock for shared access, and the lock is already held for exclusive access by a writer thread, the reader must first wait for the writer to release the lock. Similarly, if a writer thread needs to acquire a spin lock for exclusive access, and the lock is already held for shared access by one or more reader threads, the writer thread must wait for all of these reader threads to release the lock. While the writer waits, no new reader threads can acquire the lock. Instead, a reader that needs to acquire the lock that the writer is waiting for must first wait for the writer to acquire and release the lock.
A thread can switch roles between reader and writer. A thread that already holds a spin lock for shared access can try to convert the access mode of the spin lock from shared mode to exclusive mode. This attempt succeeds if no readers already hold the spin lock for shared access, and if no writer is already waiting to acquire the spin lock for exclusive access.
The reader/writer spin lock routines all take, as their first parameter, a pointer to a spin lock, which is an EX_SPIN_LOCK structure. This structure is opaque to drivers. A driver should allocate the storage for the spin lock from nonpaged system memory, and initialize the lock to zero.
If you want something "portable" in the sense of conforming to some standard... If you are using POSIX threads there is pthread_rwlock_init() and friends. These are of course not typically used on Windows but rather Unix-type OSes.
But if you mean "portable" in the sense of "portable to multiple versions of Windows..." There are some undocumented calls in ntdll which implement RW locks. RtlAcquireResourceShared() and RtlAcquireResourceExclusive().
If you don't want to use pthreads and you don't want to link to sketchy undocumented functionality... You can look up a rwlock implementation and implement it yourself in terms of other operations... Say InterlockedCompareExchange(), or perhaps higher level primitives such as semaphores and events.
You can certainly roll your own using the same ideas as slim rwlock (at least what I imagine they did, since this is fairly straightforward). I outlined the approach in some detail in this other question.
For your case, you can mostly ignore the "fair" aspect, but the implementation is essentially the same. In particular, if you are willing to let an indefinite stream of readers block writers, you always let readers in when the lock already has readers in it (i.e., state (2) and (3) more or less collapse together).
In your case, for the cross platform angle, you would need to implement the blocking with either windows events or pthread condvars - but the details are similar in either case. Or, if you really want to avoid blocking at all, your only choice is spinning (ideally using the pause instruction to be nice to the CPU), which makes things even easier by removing the whole fallback to blocking code.
Ghotit Real Writer & Reader is a Windows application that integrates with familiar Windows applications (i.e. Microsoft Word, Outlook, browsers). In addition, Ghotit Real Writer & Reader can be used as a stand-alone text editor.
Ghotit performs grammar and punctuation corrections. The corrections are performed using both grammar rules definitions and contextual spell checking algorithms that analyze the correct grammatical intention of the sentence based on the context of the sentence.
Ghotit is the only spell checker that actually learns from the input the user enters.This patented technology, enables a user to run the Ghotit spell checker, and after the user provides some inputs the user may request to re-run the Ghotit spell checker to receive more optimized results.
If you are a really bad speller then you usually have not only problems in writing but also in identifying a correct word from a list of words. Ordinary spell checkers offer you a list of candidate words. But if you are a bad speller, then you do not know for sure which word is the correct one. You need assistance in selecting the correct word. In order to overcome this hurdle, Ghotit has integrated its context spelling services with a dictionary, providing for each suggested word its meaning/s. This additional information provides the effective information for a bad speller to select the correct word from the suggested words list.
Ghotit toolbar serves the needs of slow typists who prefer to use standard editors like MS Word. It is a straightforward and clean Ghotit user interface. Personalize Ghotit by choosing the Ghotit interface that includes only the functionality serving your needs. Ghotit toolbar consists of the following functions:
3a8082e126