1/*-------------------------------------------------------------------------
2 * drawElements Thread Library
3 * ---------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Win32 implementation of mutex.
22 *//*--------------------------------------------------------------------*/
23
24#include "deMutex.h"
25
26#if (DE_OS == DE_OS_WIN32 || DE_OS == DE_OS_WINCE)
27
28#include "deMemory.h"
29
30#define VC_EXTRALEAN
31#define WIN32_LEAN_AND_MEAN
32#define NOMINMAX
33#include <windows.h>
34
35/* Critical section objects are more lightweight than mutexes on Win32. */
36#define USE_CRITICAL_SECTION 1
37
38#if defined(USE_CRITICAL_SECTION)
39
40enum
41{
42	CRITICAL_SECTION_SPIN_COUNT	= 2048
43};
44
45DE_STATIC_ASSERT(sizeof(deMutex) >= sizeof(CRITICAL_SECTION*));
46
47deMutex deMutex_create (const deMutexAttributes* attributes)
48{
49	CRITICAL_SECTION* criticalSection = (CRITICAL_SECTION*)deMalloc(sizeof(CRITICAL_SECTION));
50	if (!criticalSection)
51		return 0;
52
53	DE_UNREF(attributes);
54	/* \note [2012-11-05 pyry] Critical sections are always recursive. */
55
56	if (!InitializeCriticalSectionAndSpinCount(criticalSection, CRITICAL_SECTION_SPIN_COUNT))
57	{
58		deFree(criticalSection);
59		return 0;
60	}
61
62	return (deMutex)criticalSection;
63}
64
65void deMutex_destroy (deMutex mutex)
66{
67	DeleteCriticalSection((CRITICAL_SECTION*)mutex);
68	deFree((CRITICAL_SECTION*)mutex);
69}
70
71void deMutex_lock (deMutex mutex)
72{
73	EnterCriticalSection((CRITICAL_SECTION*)mutex);
74}
75
76void deMutex_unlock (deMutex mutex)
77{
78	LeaveCriticalSection((CRITICAL_SECTION*)mutex);
79}
80
81deBool deMutex_tryLock (deMutex mutex)
82{
83	return TryEnterCriticalSection((CRITICAL_SECTION*)mutex) == TRUE;
84}
85
86#else
87
88DE_STATIC_ASSERT(sizeof(deMutex) >= sizeof(HANDLE));
89
90deMutex deMutex_create (const deMutexAttributes* attributes)
91{
92	HANDLE handle = DE_NULL;
93
94	DE_UNREF(attributes);
95	/* \note [2009-11-12 pyry] Created mutex is always recursive. */
96
97	handle = CreateMutex(DE_NULL, FALSE, DE_NULL);
98	return (deMutex)handle;
99}
100
101void deMutex_destroy (deMutex mutex)
102{
103	HANDLE handle = (HANDLE)mutex;
104	CloseHandle(handle);
105}
106
107void deMutex_lock (deMutex mutex)
108{
109	HANDLE	handle	= (HANDLE)mutex;
110	DWORD	ret		= WaitForSingleObject(handle, INFINITE);
111	DE_ASSERT(ret == WAIT_OBJECT_0);
112}
113
114void deMutex_unlock (deMutex mutex)
115{
116	HANDLE	handle	= (HANDLE)mutex;
117	BOOL	ret		= ReleaseMutex(handle);
118	DE_ASSERT(ret == TRUE);
119}
120
121deBool deMutex_tryLock (deMutex mutex)
122{
123	HANDLE	handle	= (HANDLE)mutex;
124	DWORD	ret		= WaitForSingleObject(handle, 0);
125	return (ret == WAIT_OBJECT_0);
126}
127
128#endif /* USE_CRITICAL_SECTION */
129
130#endif /* DE_OS */
131