[glib/wip/mutexes] win32: Add 'shared' support to SRWLock emulation
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/mutexes] win32: Add 'shared' support to SRWLock emulation
- Date: Wed, 21 Sep 2011 03:43:40 +0000 (UTC)
commit 3b370e28a3e22c1e7562b437b723ba3972e82351
Author: Ryan Lortie <desrt desrt ca>
Date: Tue Sep 20 10:06:57 2011 -0400
win32: Add 'shared' support to SRWLock emulation
glib/gthread-win32.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 108 insertions(+), 0 deletions(-)
---
diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c
index 89d8f11..00702c7 100644
--- a/glib/gthread-win32.c
+++ b/glib/gthread-win32.c
@@ -106,6 +106,9 @@ typedef struct
void (__stdcall * AcquireSRWLockExclusive) (gpointer lock);
BOOLEAN (__stdcall * TryAcquireSRWLockExclusive) (gpointer lock);
void (__stdcall * ReleaseSRWLockExclusive) (gpointer lock);
+ void (__stdcall * AcquireSRWLockShared) (gpointer lock);
+ BOOLEAN (__stdcall * TryAcquireSRWLockShared) (gpointer lock);
+ void (__stdcall * ReleaseSRWLockShared) (gpointer lock);
void (__stdcall * InitializeConditionVariable) (gpointer cond);
void (__stdcall * DeleteConditionVariable) (gpointer cond); /* fake */
@@ -522,6 +525,12 @@ g_thread_xp_CallThisOnThreadExit (void)
typedef struct
{
CRITICAL_SECTION writer_lock;
+ gboolean ever_shared; /* protected by writer_lock */
+
+ /* below is only ever touched if ever_shared becomes true */
+ CRITICAL_SECTION atomicity;
+ GThreadXpWaiter *queued_writer; /* protected by atomicity lock */
+ gint num_readers; /* protected by atomicity lock */
} GThreadSRWLock;
static void __stdcall
@@ -537,6 +546,9 @@ g_thread_xp_DeleteSRWLock (gpointer mutex)
if (lock)
{
+ if (lock->ever_shared)
+ DeleteCriticalSection (&lock->atomicity);
+
DeleteCriticalSection (&lock->writer_lock);
free (lock);
}
@@ -564,6 +576,7 @@ g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock)
g_thread_abort (errno, "malloc");
InitializeCriticalSection (&result->writer_lock);
+ result->ever_shared = FALSE;
*lock = result;
LeaveCriticalSection (&g_thread_xp_lock);
@@ -578,6 +591,21 @@ g_thread_xp_AcquireSRWLockExclusive (gpointer mutex)
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
EnterCriticalSection (&lock->writer_lock);
+
+ if (lock->ever_shared)
+ {
+ GThreadXpWaiter *waiter = NULL;
+
+ EnterCriticalSection (&lock->atomicity);
+ if (lock->num_readers > 0)
+ lock->queued_writer = waiter = g_thread_xp_waiter_get ();
+ LeaveCriticalSection (&lock->atomicity);
+
+ if (waiter != NULL)
+ WaitForSingleObject (waiter->event, INFINITE);
+
+ lock->queued_writer = NULL;
+ }
}
static BOOLEAN __stdcall
@@ -588,6 +616,21 @@ g_thread_xp_TryAcquireSRWLockExclusive (gpointer mutex)
if (!TryEnterCriticalSection (&lock->writer_lock))
return FALSE;
+ if (lock->ever_shared)
+ {
+ gboolean available;
+
+ EnterCriticalSection (&lock->atomicity);
+ available = lock->num_readers == 0;
+ LeaveCriticalSection (&lock->atomicity);
+
+ if (!available)
+ {
+ LeaveCriticalSection (&lock->writer_lock);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
@@ -603,6 +646,65 @@ g_thread_xp_ReleaseSRWLockExclusive (gpointer mutex)
LeaveCriticalSection (&lock->writer_lock);
}
+static void
+g_thread_xp_srwlock_become_reader (GThreadSRWLock *lock)
+{
+ if G_UNLIKELY (!lock->ever_shared)
+ {
+ InitializeCriticalSection (&lock->atomicity);
+ lock->queued_writer = NULL;
+ lock->num_readers = 0;
+
+ lock->ever_shared = TRUE;
+ }
+
+ EnterCriticalSection (&lock->atomicity);
+ lock->num_readers++;
+ LeaveCriticalSection (&lock->atomicity);
+}
+
+static void __stdcall
+g_thread_xp_AcquireSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ EnterCriticalSection (&lock->writer_lock);
+
+ g_thread_xp_srwlock_become_reader (lock);
+
+ LeaveCriticalSection (&lock->writer_lock);
+}
+
+static BOOLEAN __stdcall
+g_thread_xp_TryAcquireSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ if (!TryEnterCriticalSection (&lock->writer_lock))
+ return FALSE;
+
+ g_thread_xp_srwlock_become_reader (lock);
+
+ LeaveCriticalSection (&lock->writer_lock);
+
+ return TRUE;
+}
+
+static void __stdcall
+g_thread_xp_ReleaseSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ EnterCriticalSection (&lock->atomicity);
+
+ lock->num_readers--;
+
+ if (lock->num_readers == 0 && lock->queued_writer)
+ SetEvent (lock->queued_writer->event);
+
+ LeaveCriticalSection (&lock->atomicity);
+}
+
/* {{{2 CONDITION_VARIABLE emulation */
typedef struct
{
@@ -738,6 +840,9 @@ g_thread_xp_init (void)
g_thread_xp_AcquireSRWLockExclusive,
g_thread_xp_TryAcquireSRWLockExclusive,
g_thread_xp_ReleaseSRWLockExclusive,
+ g_thread_xp_AcquireSRWLockShared,
+ g_thread_xp_TryAcquireSRWLockShared,
+ g_thread_xp_ReleaseSRWLockShared,
g_thread_xp_InitializeConditionVariable,
g_thread_xp_DeleteConditionVariable,
g_thread_xp_SleepConditionVariableSRW,
@@ -786,6 +891,9 @@ g_thread_lookup_native_funcs (void)
GET_FUNC(AcquireSRWLockExclusive);
GET_FUNC(TryAcquireSRWLockExclusive);
GET_FUNC(ReleaseSRWLockExclusive);
+ GET_FUNC(AcquireSRWLockShared);
+ GET_FUNC(TryAcquireSRWLockShared);
+ GET_FUNC(ReleaseSRWLockShared);
GET_FUNC(InitializeConditionVariable);
GET_FUNC(SleepConditionVariableSRW);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]