Design Pattern Examples
Overview of object-oriented design patterns
mutex.c
Go to the documentation of this file.
1
5
6#include <stdlib.h>
7#include <stdio.h>
8
9#ifdef _MSC_VER
10#include <Windows.h>
11#define MUTEX_TYPE HANDLE
12#else
13#include <threads.h>
14#define MUTEX_TYPE mtx_t
15#endif
16
17#include "mutex.h"
18
19//-----------------------------------------------------------------------------
20// The following functions are used to hide the differences between different
21// mutex handles by storing a copy of the handle in allocated heap space. The
22// pointer to the copy is then kept as an opaque handle.
23//
24// The MUTEX_TYPE macro contains the actual type of the mutex handle for each
25// operating system.
26//-----------------------------------------------------------------------------
27
34static MUTEX_TYPE _get_mutex_handle(void* handle)
35{
36 return *(MUTEX_TYPE*)handle;
37}
38
47{
48 void *handle_ptr = malloc(sizeof(MUTEX_TYPE));
49 if (handle_ptr != NULL)
50 {
51 *(MUTEX_TYPE*)handle_ptr = handle;
52 }
53 return handle_ptr;
54}
55
61static void _deallocate_mutex_handle(void *handle)
62{
63 free(handle);
64}
65
66//-----------------------------------------------------------------------------
67
69// mutex_create()
71bool mutex_create(Mutex* mutex)
72{
73 bool created = false;
74
75 if (mutex != NULL)
76 {
77 mutex->handle = NULL;
78#ifdef _MSC_VER
79 HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
80 if (hMutex != NULL)
81 {
82 mutex->handle = _allocate_mutex_handle(hMutex);
83 if (mutex->handle != NULL)
84 {
85 // mutex->handle = hMutex;
86 created = true;
87 }
88 else
89 {
90 printf("Error! Out of memory saving mutex handle.\n");
91 CloseHandle(hMutex);
92 }
93 }
94 else
95 {
96 DWORD lastError = GetLastError();
97 printf("Error (0x%x)! Failed to create a mutex.\n", lastError);
98 }
99#else
100 mtx_t mutex_handle;
101 int err = mtx_init(&mutex_handle, mtx_plain);
102 if (err == thrd_success)
103 {
104 mutex->handle = _allocate_mutex_handle(mutex_handle);
105 if (mutex->handle != NULL)
106 {
107 created = true;
108 }
109 else
110 {
111 printf("Error! Out of memory saving mutex handle.\n");
112 mtx_destroy(&mutex_handle);
113 }
114 }
115 else
116 {
117 printf("Error! Failed to create a mutex.\n");
118 }
119#endif
120 }
121
122 return created;
123}
124
126// mutex_destroy()
129{
130 bool destroyed = false;
131
132 if (mutex != NULL && mutex->handle != NULL)
133 {
134#ifdef _MSC_VER
135 HANDLE hMutex = _get_mutex_handle(mutex->handle);
136 if (CloseHandle(hMutex))
137 {
138 destroyed = true;
139 }
140 else
141 {
142 DWORD lastError = GetLastError();
143 printf("Error (0x%x)! Failed to destroy the mutex.\n", lastError);
144 }
145#else
146 mtx_t mutex_handle = _get_mutex_handle(mutex->handle);
147 mtx_destroy(&mutex_handle);
148 destroyed = true;
149#endif
151 mutex->handle = NULL;
152 }
153
154 return destroyed;
155}
156
158// mutex_lock()
160bool mutex_lock(Mutex* mutex)
161{
162 bool locked = false;
163
164 if (mutex != NULL && mutex->handle != NULL)
165 {
166#ifdef _MSC_VER
167 HANDLE hMutex = _get_mutex_handle(mutex->handle);
168 DWORD waitResult = WaitForSingleObject(hMutex, INFINITE);
169 if (waitResult == WAIT_OBJECT_0)
170 {
171 locked = true;
172 }
173 else if (waitResult == WAIT_ABANDONED)
174 {
175 printf("Error! While attempting to lock a mutex, it was found to be abandoned.\n");
176 }
177#else
178 mtx_t mutex_handle = _get_mutex_handle(mutex->handle);
179 int err = mtx_lock(&mutex_handle);
180 if (err == thrd_success)
181 {
182 locked = true;
183 }
184 else
185 {
186 printf("Error! Failed to lock a mutex.\n");
187 }
188#endif
189 }
190
191 return locked;
192}
193
195// mutex_unlock()
197bool mutex_unlock(Mutex* mutex)
198{
199 bool unlocked = false;
200
201 if (mutex != NULL && mutex->handle != NULL)
202 {
203#ifdef _MSC_VER
204 HANDLE hMutex = _get_mutex_handle(mutex->handle);
205 if (ReleaseMutex(hMutex))
206 {
207 unlocked = true;
208 }
209 else
210 {
211 DWORD lastError = GetLastError();
212 printf("Error (0x%x)! Failed to unlock a mutex.\n", lastError);
213 }
214#else
215 mtx_t mutex_handle = _get_mutex_handle(mutex->handle);
216 int err = mtx_unlock(&mutex_handle);
217 if (err == thrd_success)
218 {
219 unlocked = true;
220 }
221 else
222 {
223 printf("Error! Failed to unlock a mutex.\n");
224 }
225#endif
226 }
227
228 return unlocked;
229}
static void _deallocate_mutex_handle(void *handle)
Helper function to deallocate memory that contained a mutex handle. The mutex handle itself should be...
Definition: mutex.c:61
bool mutex_destroy(Mutex *mutex)
Destroy a previously created mutex.
Definition: mutex.c:128
bool mutex_unlock(Mutex *mutex)
Unlock a previously locked mutex.
Definition: mutex.c:197
bool mutex_create(Mutex *mutex)
Create a new mutex, which is initially not owned.
Definition: mutex.c:71
static void * _allocate_mutex_handle(MUTEX_TYPE handle)
Helper function to allocate memory from the heap in which to store the given mutex handle....
Definition: mutex.c:46
#define MUTEX_TYPE
Definition: mutex.c:14
static MUTEX_TYPE _get_mutex_handle(void *handle)
Helper function to retrieve the mutex handle from the given memory pointer.
Definition: mutex.c:34
bool mutex_lock(Mutex *mutex)
Lock a previously created and unlocked mutex. This will block if the mutex is already locked by some ...
Definition: mutex.c:160
Declaration of the Mutex structure and supporting functions for working with mutexes.
Represents a handle to a mutex. Call mutex_create() to create the mutex and mutex_destroy() to destro...
Definition: mutex.h:16
void * handle
An opaque value that represents the operating system-specific mutex.
Definition: mutex.h:21