mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
Implemented resource (multiple-reader-single-writer) lock
svn path=/trunk/; revision=1913
This commit is contained in:
parent
56ab538abe
commit
ca61cc2444
5 changed files with 400 additions and 21 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: rtl.h,v 1.25 2001/05/07 22:03:26 chorns Exp $
|
||||
/* $Id: rtl.h,v 1.26 2001/05/24 11:27:10 ekohl Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -37,6 +37,18 @@ typedef struct _RTL_PROCESS_INFO
|
|||
SECTION_IMAGE_INFORMATION ImageInfo;
|
||||
} RTL_PROCESS_INFO, *PRTL_PROCESS_INFO;
|
||||
|
||||
typedef struct _RTL_RESOURCE
|
||||
{
|
||||
CRITICAL_SECTION Lock;
|
||||
HANDLE SharedSemaphore;
|
||||
ULONG SharedWaiters;
|
||||
HANDLE ExclusiveSemaphore;
|
||||
ULONG ExclusiveWaiters;
|
||||
LONG NumberActive;
|
||||
HANDLE OwningThread;
|
||||
ULONG TimeoutBoost; /* ?? */
|
||||
PVOID DebugInfo; /* ?? */
|
||||
} RTL_RESOURCE, *PRTL_RESOURCE;
|
||||
|
||||
|
||||
#define HEAP_BASE (0xa0000000)
|
||||
|
@ -335,6 +347,59 @@ RtlRaiseStatus (
|
|||
IN NTSTATUS Status
|
||||
);
|
||||
|
||||
|
||||
/* resource functions */
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
RtlAcquireResourceExclusive (
|
||||
IN PRTL_RESOURCE Resource,
|
||||
IN BOOLEAN Wait
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
RtlAcquireResourceShared (
|
||||
IN PRTL_RESOURCE Resource,
|
||||
IN BOOLEAN Wait
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlConvertExclusiveToShared (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlConvertSharedToExclusive (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlDeleteResource (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlDumpResource (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlInitializeResource (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
RtlReleaseResource (
|
||||
IN PRTL_RESOURCE Resource
|
||||
);
|
||||
|
||||
#endif /* __INCLUDE_NTDLL_RTL_H */
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; $Id: ntdll.def,v 1.70 2001/05/02 22:23:47 ekohl Exp $
|
||||
; $Id: ntdll.def,v 1.71 2001/05/24 11:28:18 ekohl Exp $
|
||||
;
|
||||
; ReactOS Operating System
|
||||
;
|
||||
|
@ -271,8 +271,8 @@ NtYieldExecution@0
|
|||
;RtlAbortRXact
|
||||
RtlAbsoluteToSelfRelativeSD@12
|
||||
RtlAcquirePebLock@0
|
||||
;RtlAcqureResourceExclusive
|
||||
;RtlAcqureResourceShared
|
||||
RtlAcquireResourceExclusive@8
|
||||
RtlAcquireResourceShared@8
|
||||
RtlAddAccessAllowedAce@16
|
||||
RtlAddAccessDeniedAce@16
|
||||
RtlAddAce@20
|
||||
|
@ -312,9 +312,9 @@ RtlCompareString@12
|
|||
RtlCompareUnicodeString@12
|
||||
;RtlCompressBuffer
|
||||
;RtlConsoleMultiByteToUnicodeN
|
||||
;RtlConvertExclusiveToShared
|
||||
RtlConvertExclusiveToShared@4
|
||||
RtlConvertLongToLargeInteger@4
|
||||
;RtlConvertSharedToExclusive
|
||||
RtlConvertSharedToExclusive@4
|
||||
RtlConvertSidToUnicodeString@12
|
||||
;RtlConvertUiListToApiList
|
||||
RtlConvertUlongToLargeInteger@4
|
||||
|
@ -353,7 +353,7 @@ RtlDeleteCriticalSection@4
|
|||
;RtlDeleteElementGenericTable
|
||||
;RtlDeleteNoSplay
|
||||
RtlDeleteRegistryValue@12
|
||||
;RtlDeleteResource
|
||||
RtlDeleteResource@4
|
||||
;RtlDeleteSecurityObject
|
||||
;RtlDestroyAtomTable
|
||||
RtlDestroyEnvironment@4
|
||||
|
@ -366,7 +366,7 @@ RtlDoesFileExists_U@4
|
|||
RtlDosPathNameToNtPathName_U@16
|
||||
RtlDosSearchPath_U@24
|
||||
RtlDowncaseUnicodeString@12
|
||||
;RtlDumpResource
|
||||
RtlDumpResource@4
|
||||
;RtlEmptyAtomTable
|
||||
RtlEnlargedIntegerMultiply@8
|
||||
RtlEnlargedUnsignedDivide@16
|
||||
|
@ -446,7 +446,7 @@ RtlInitializeCriticalSection@4
|
|||
;RtlInitializeGenericTable
|
||||
;RtlInitializeHandleTable
|
||||
;RtlInitializeRXact
|
||||
;RtlInitializeResource
|
||||
RtlInitializeResource@4
|
||||
RtlInitializeSid@12
|
||||
;RtlInsertElementGenericTable
|
||||
RtlIntegerToChar@16
|
||||
|
@ -518,7 +518,7 @@ RtlReAllocateHeap@16
|
|||
;RtlRealPredecessor
|
||||
;RtlRealSuccessor
|
||||
RtlReleasePebLock@0
|
||||
;RtlReleaseResource
|
||||
RtlReleaseResource@4
|
||||
;RtlRemoteCall
|
||||
;RtlResetRtlTranslations
|
||||
;RtlRunDecodeUnicodeString
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; $Id: ntdll.edf,v 1.59 2001/05/02 22:23:47 ekohl Exp $
|
||||
; $Id: ntdll.edf,v 1.60 2001/05/24 11:28:18 ekohl Exp $
|
||||
;
|
||||
; ReactOS Operating System
|
||||
;
|
||||
|
@ -271,8 +271,8 @@ NtYieldExecution=NtYieldExecution@0
|
|||
;RtlAbortRXact
|
||||
RtlAbsoluteToSelfRelativeSD=RtlAbsoluteToSelfRelativeSD@12
|
||||
RtlAcquirePebLock=RtlAcquirePebLock@0
|
||||
;RtlAcqureResourceExclusive
|
||||
;RtlAcqureResourceShared
|
||||
RtlAcquireResourceExclusive=RtlAcquireResourceExclusive@8
|
||||
RtlAcquireResourceShared=RtlAcquireResourceShared@8
|
||||
RtlAddAccessAllowedAce=RtlAddAccessAllowedAce@16
|
||||
RtlAddAccessDeniedAce=RtlAddAccessDeniedAce@16
|
||||
RtlAddAce=RtlAddAce@20
|
||||
|
@ -312,9 +312,9 @@ RtlCompareString=RtlCompareString@12
|
|||
RtlCompareUnicodeString=RtlCompareUnicodeString@12
|
||||
;RtlCompressBuffer
|
||||
;RtlConsoleMultiByteToUnicodeN
|
||||
;RtlConvertExclusiveToShared
|
||||
RtlConvertExclusiveToShared=RtlConvertExclusiveToShared@4
|
||||
RtlConvertLongToLargeInteger=RtlConvertLongToLargeInteger@4
|
||||
;RtlConvertSharedToExclusive
|
||||
RtlConvertSharedToExclusive=RtlConvertSharedToExclusive@4
|
||||
RtlConvertSidToUnicodeString=RtlConvertSidToUnicodeString@12
|
||||
;RtlConvertUiListToApiList
|
||||
RtlConvertUlongToLargeInteger=RtlConvertUlongToLargeInteger@4
|
||||
|
@ -353,7 +353,7 @@ RtlDeleteCriticalSection=RtlDeleteCriticalSection@4
|
|||
;RtlDeleteElementGenericTable
|
||||
;RtlDeleteNoSplay
|
||||
RtlDeleteRegistryValue=RtlDeleteRegistryValue@12
|
||||
;RtlDeleteResource
|
||||
RtlDeleteResource=RtlDeleteResource@4
|
||||
;RtlDeleteSecurityObject
|
||||
;RtlDestroyAtomTable
|
||||
RtlDestroyEnvironment=RtlDestroyEnvironment@4
|
||||
|
@ -366,7 +366,7 @@ RtlDoesFileExists_U=RtlDoesFileExists_U@4
|
|||
RtlDosPathNameToNtPathName_U=RtlDosPathNameToNtPathName_U@16
|
||||
RtlDosSearchPath_U=RtlDosSearchPath_U@24
|
||||
RtlDowncaseUnicodeString=RtlDowncaseUnicodeString@12
|
||||
;RtlDumpResource
|
||||
RtlDumpResource=RtlDumpResource@4
|
||||
;RtlEmptyAtomTable
|
||||
RtlEnlargedIntegerMultiply=RtlEnlargedIntegerMultiply@8
|
||||
RtlEnlargedUnsignedDivide=RtlEnlargedUnsignedDivide@16
|
||||
|
@ -445,7 +445,7 @@ RtlInitializeCriticalSection=RtlInitializeCriticalSection@4
|
|||
;RtlInitializeGenericTable
|
||||
;RtlInitializeHandleTable
|
||||
;RtlInitializeRXact
|
||||
;RtlInitializeResource
|
||||
RtlInitializeResource=RtlInitializeResource@4
|
||||
RtlInitializeSid=RtlInitializeSid@12
|
||||
;RtlInsertElementGenericTable
|
||||
RtlIntegerToChar=RtlIntegerToChar@16
|
||||
|
@ -517,7 +517,7 @@ RtlReAllocateHeap=RtlReAllocateHeap@16
|
|||
;RtlRealPredecessor
|
||||
;RtlRealSuccessor
|
||||
RtlReleasePebLock=RtlReleasePebLock@0
|
||||
;RtlReleaseResource
|
||||
RtlReleaseResource=RtlReleaseResource@4
|
||||
;RtlRemoteCall
|
||||
;RtlResetRtlTranslations
|
||||
;RtlRunDecodeUnicodeString
|
||||
|
@ -822,7 +822,18 @@ __isascii
|
|||
__iscsym
|
||||
__iscsymf
|
||||
__toascii
|
||||
;_alldiv
|
||||
;_allmul
|
||||
;_alloca_probe
|
||||
;_allrem
|
||||
;_allshl
|
||||
;_allshr
|
||||
_atoi64
|
||||
;_aulldiv
|
||||
;_aullrem
|
||||
;_aullshr
|
||||
;_chkstk
|
||||
;_fltused
|
||||
_ftol
|
||||
_i64toa
|
||||
_i64tow
|
||||
|
@ -886,6 +897,7 @@ qsort
|
|||
sin
|
||||
sprintf
|
||||
sqrt
|
||||
;sscanf
|
||||
strcat
|
||||
strchr
|
||||
strcmp
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.58 2001/01/21 00:07:51 phreak Exp $
|
||||
# $Id: makefile,v 1.59 2001/05/24 11:28:54 ekohl Exp $
|
||||
#
|
||||
# ReactOS Operating System
|
||||
#
|
||||
|
@ -24,7 +24,7 @@ RTL_OBJECTS = rtl/critical.o rtl/error.o rtl/heap.o rtl/largeint.o \
|
|||
rtl/thread.o rtl/unicode.o rtl/env.o rtl/path.o rtl/ppb.o \
|
||||
rtl/bitmap.o rtl/time.o rtl/acl.o rtl/sid.o rtl/image.o \
|
||||
rtl/access.o rtl/apc.o rtl/callback.o rtl/luid.o rtl/misc.o \
|
||||
rtl/registry.o rtl/exception.o rtl/intrlck.o
|
||||
rtl/registry.o rtl/exception.o rtl/intrlck.o rtl/resource.o
|
||||
|
||||
STDIO_OBJECTS = stdio/sprintf.o stdio/swprintf.o
|
||||
|
||||
|
|
302
reactos/lib/ntdll/rtl/resource.c
Normal file
302
reactos/lib/ntdll/rtl/resource.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/* $Id: resource.c,v 1.1 2001/05/24 11:28:00 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/ntdll/rtl/resource.c
|
||||
* PURPOSE: Resource (multiple-reader-single-writer lock) functions
|
||||
* PROGRAMMER:
|
||||
* UPDATE HISTORY:
|
||||
* Created 24/05/2001
|
||||
*
|
||||
* NOTES: Partially take from Wine:
|
||||
* Copyright 1996-1998 Marcus Meissner
|
||||
* 1999 Alex Korobka
|
||||
*/
|
||||
|
||||
/*
|
||||
* xxxResource() functions implement multiple-reader-single-writer lock.
|
||||
* The code is based on information published in WDJ January 1999 issue.
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ntdll/rtl.h>
|
||||
#include <ntos/synch.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <ntdll/ntdll.h>
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
VOID STDCALL
|
||||
RtlInitializeResource(PRTL_RESOURCE Resource)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = RtlInitializeCriticalSection(&Resource->Lock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlRaiseStatus(Status);
|
||||
}
|
||||
|
||||
Status = NtCreateSemaphore(&Resource->SharedSemaphore,
|
||||
SEMAPHORE_ALL_ACCESS,
|
||||
NULL,
|
||||
0,
|
||||
65535);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlRaiseStatus(Status);
|
||||
}
|
||||
Resource->SharedWaiters = 0;
|
||||
|
||||
Status = NtCreateSemaphore(&Resource->ExclusiveSemaphore,
|
||||
SEMAPHORE_ALL_ACCESS,
|
||||
NULL,
|
||||
0,
|
||||
65535);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlRaiseStatus(Status);
|
||||
}
|
||||
Resource->ExclusiveWaiters = 0;
|
||||
|
||||
Resource->NumberActive = 0;
|
||||
Resource->OwningThread = NULL;
|
||||
Resource->TimeoutBoost = 0; /* no info on this one, default value is 0 */
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
RtlDeleteResource(PRTL_RESOURCE Resource)
|
||||
{
|
||||
RtlDeleteCriticalSection(&Resource->Lock);
|
||||
NtClose(Resource->ExclusiveSemaphore);
|
||||
NtClose(Resource->SharedSemaphore);
|
||||
Resource->OwningThread = NULL;
|
||||
Resource->ExclusiveWaiters = 0;
|
||||
Resource->SharedWaiters = 0;
|
||||
Resource->NumberActive = 0;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN STDCALL
|
||||
RtlAcquireResourceExclusive(PRTL_RESOURCE Resource,
|
||||
BOOLEAN Wait)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN retVal = FALSE;
|
||||
|
||||
start:
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
if (Resource->NumberActive == 0) /* lock is free */
|
||||
{
|
||||
Resource->NumberActive = -1;
|
||||
retVal = TRUE;
|
||||
}
|
||||
else if (Resource->NumberActive < 0) /* exclusive lock in progress */
|
||||
{
|
||||
if (Resource->OwningThread == NtCurrentTeb()->Cid.UniqueThread)
|
||||
{
|
||||
retVal = TRUE;
|
||||
Resource->NumberActive--;
|
||||
goto done;
|
||||
}
|
||||
wait:
|
||||
if (Wait == TRUE)
|
||||
{
|
||||
Resource->ExclusiveWaiters++;
|
||||
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto done;
|
||||
goto start; /* restart the acquisition to avoid deadlocks */
|
||||
}
|
||||
}
|
||||
else /* one or more shared locks are in progress */
|
||||
{
|
||||
if (Wait == TRUE)
|
||||
goto wait;
|
||||
}
|
||||
if (retVal == TRUE)
|
||||
Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread;
|
||||
done:
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN STDCALL
|
||||
RtlAcquireResourceShared(PRTL_RESOURCE Resource,
|
||||
BOOLEAN Wait)
|
||||
{
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
BOOLEAN retVal = FALSE;
|
||||
|
||||
start:
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
if (Resource->NumberActive < 0)
|
||||
{
|
||||
if (Resource->OwningThread == NtCurrentTeb()->Cid.UniqueThread)
|
||||
{
|
||||
Resource->NumberActive--;
|
||||
retVal = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (Wait == TRUE)
|
||||
{
|
||||
Resource->SharedWaiters++;
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
Status = NtWaitForSingleObject(Resource->SharedSemaphore,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto done;
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Status != STATUS_WAIT_0) /* otherwise RtlReleaseResource() has already done it */
|
||||
Resource->NumberActive++;
|
||||
retVal = TRUE;
|
||||
}
|
||||
done:
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
RtlConvertExclusiveToShared(PRTL_RESOURCE Resource)
|
||||
{
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
|
||||
if (Resource->NumberActive == -1)
|
||||
{
|
||||
Resource->OwningThread = NULL;
|
||||
|
||||
if (Resource->SharedWaiters > 0)
|
||||
{
|
||||
ULONG n;
|
||||
/* prevent new writers from joining until
|
||||
* all queued readers have done their thing */
|
||||
n = Resource->SharedWaiters;
|
||||
Resource->NumberActive = Resource->SharedWaiters + 1;
|
||||
Resource->SharedWaiters = 0;
|
||||
NtReleaseSemaphore(Resource->SharedSemaphore,
|
||||
n,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Resource->NumberActive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
RtlConvertSharedToExclusive(PRTL_RESOURCE Resource)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
|
||||
if (Resource->NumberActive == 1)
|
||||
{
|
||||
Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread;
|
||||
Resource->NumberActive = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Resource->ExclusiveWaiters++;
|
||||
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return;
|
||||
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread;
|
||||
Resource->NumberActive = -1;
|
||||
}
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
RtlReleaseResource(PRTL_RESOURCE Resource)
|
||||
{
|
||||
RtlEnterCriticalSection(&Resource->Lock);
|
||||
|
||||
if (Resource->NumberActive > 0) /* have one or more readers */
|
||||
{
|
||||
Resource->NumberActive--;
|
||||
if (Resource->NumberActive == 0)
|
||||
{
|
||||
if (Resource->ExclusiveWaiters > 0)
|
||||
{
|
||||
wake_exclusive:
|
||||
Resource->ExclusiveWaiters--;
|
||||
NtReleaseSemaphore(Resource->ExclusiveSemaphore,
|
||||
1,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Resource->NumberActive < 0) /* have a writer, possibly recursive */
|
||||
{
|
||||
Resource->NumberActive++;
|
||||
if (Resource->NumberActive == 0)
|
||||
{
|
||||
Resource->OwningThread = 0;
|
||||
if (Resource->ExclusiveWaiters > 0)
|
||||
{
|
||||
goto wake_exclusive;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Resource->SharedWaiters > 0)
|
||||
{
|
||||
ULONG n;
|
||||
/* prevent new writers from joining until
|
||||
* all queued readers have done their thing */
|
||||
n = Resource->SharedWaiters;
|
||||
Resource->NumberActive = Resource->SharedWaiters;
|
||||
Resource->SharedWaiters = 0;
|
||||
NtReleaseSemaphore(Resource->SharedSemaphore,
|
||||
n,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection(&Resource->Lock);
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
RtlDumpResource(PRTL_RESOURCE Resource)
|
||||
{
|
||||
DbgPrint("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
|
||||
Resource,
|
||||
Resource->NumberActive,
|
||||
Resource->SharedWaiters,
|
||||
Resource->ExclusiveWaiters);
|
||||
if (Resource->NumberActive != 0)
|
||||
{
|
||||
DbgPrint("\towner thread = %08x\n",
|
||||
Resource->OwningThread);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue