Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
recmutex.h
Go to the documentation of this file.
1/*
2 recmutex.h - recursive mutual exclusion locking
3
4 Copyright (C)
5 2008, 2009, Christian Thaeter <ct@pipapo.org>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11*/
12
13#ifndef LUMIERA_RECMUTEX_H
14#define LUMIERA_RECMUTEX_H
15
16#include "lib/error.h"
17#include "lib/sectionlock.h"
18#include "lib/lockerror.h"
19#include "lib/mutex.h"
20
21#include <pthread.h>
22#include <nobug.h>
23
32#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \
33 for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
34 lumiera_lock_section_ = { \
35 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
36 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
37 ({ \
38 if (lumiera_lock_section_.lock) \
39 lumiera_lock_section_.lock = \
40 lumiera_recmutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
41 &lumiera_lock_section_.rh, NOBUG_CONTEXT); \
42 lumiera_lock_section_.lock; \
43 }); \
44 ({ \
45 LUMIERA_RECMUTEX_SECTION_UNLOCK; \
46 }))
47
48
49#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \
50 for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \
51 NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \
52 mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \
53 NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \
54 ({ \
55 if (lumiera_lock_section_.lock) \
56 { \
57 REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \
58 lumiera_lock_section_.lock = \
59 lumiera_recmutex_lock (mtx, &NOBUG_FLAG(nobugflag), \
60 lumiera_lock_section_.rh, NOBUG_CONTEXT); \
61 LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \
62 } \
63 lumiera_lock_section_.lock; \
64 }); \
65 ({ \
66 LUMIERA_RECMUTEX_SECTION_UNLOCK; \
67 }))
68
69
70#define LUMIERA_RECMUTEX_SECTION_UNLOCK \
71 LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_)
72
73
74
80{
81 pthread_mutex_t recmutex;
83};
84typedef struct lumiera_recmutex_struct lumiera_recmutex;
85typedef lumiera_recmutex* LumieraRecmutex;
86
95 const char* purpose,
96 struct nobug_flag* flag,
97 const struct nobug_context ctx);
98
106 struct nobug_flag* flag,
107 const struct nobug_context ctx);
108
109
110static inline LumieraRecmutex
112 struct nobug_flag* flag,
113 struct nobug_resource_user** handle,
114 const struct nobug_context ctx)
115{
116 if (self)
117 {
118 NOBUG_RESOURCE_WAIT_CTX (NOBUG_FLAG_RAW(flag), self->rh, "acquire mutex", *handle, ctx)
119 {
120 if (pthread_mutex_lock (&self->recmutex))
121 LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */
122
123 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle, ctx) /*{}*/;
124 }
125 }
126
127 return self;
128}
129
130
131static inline LumieraRecmutex
133 struct nobug_flag* flag,
134 struct nobug_resource_user** handle,
135 const struct nobug_context ctx)
136{
137 if (self)
138 {
139 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "try acquire mutex", *handle, ctx)
140 {
141 int err = pthread_mutex_trylock (&self->recmutex);
142
143 if (!err)
144 {
145 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle, ctx) /*{}*/;
146 }
147 else
148 {
149 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) /*{}*/;
150 lumiera_lockerror_set (err, flag, ctx);
151 self = NULL;
152 }
153 }
154 }
155
156 return self;
157}
158
159
160static inline LumieraRecmutex
162 const struct timespec* timeout,
163 struct nobug_flag* flag,
164 struct nobug_resource_user** handle,
165 const struct nobug_context ctx)
166{
167 if (self)
168 {
169 NOBUG_RESOURCE_TRY_CTX (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire mutex", *handle, ctx)
170 {
171 int err = pthread_mutex_timedlock (&self->recmutex, timeout);
172
173 if (!err)
174 {
175 NOBUG_RESOURCE_STATE_CTX (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle, ctx) /*{}*/;
176 }
177 else
178 {
179 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx) /*{}*/;
180 lumiera_lockerror_set (err, flag, ctx);
181 self = NULL;
182 }
183 }
184 }
185
186 return self;
187}
188
189
190static inline void
192 struct nobug_flag* flag,
193 struct nobug_resource_user** handle,
194 const struct nobug_context ctx)
195{
196 NOBUG_REQUIRE_CTX (self, ctx);
197
198 NOBUG_RESOURCE_LEAVE_RAW_CTX (flag, *handle, ctx)
199 {
200 if (pthread_mutex_unlock (&self->recmutex))
201 LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */
202 }
203}
204
205
206#endif
207/*
208// Local Variables:
209// mode: C
210// c-file-style: "gnu"
211// indent-tabs-mode: nil
212// End:
213*/
Lumiera error handling (C interface).
#define LUMIERA_DIE(err)
Abort unconditionally with a 'Fatal Error!' message.
Definition error.h:54
return NULL
Definition llist.h:586
void lumiera_lockerror_set(int err, struct nobug_flag *flag, const struct nobug_context ctx)
Translate pthread error code into lumiera error.
Definition lockerror.c:40
definitions and declarations for error-handling on low-level locking
Mutual exclusion locking, header.
LumieraRecmutex lumiera_recmutex_init(LumieraRecmutex self, const char *purpose, struct nobug_flag *flag, const struct nobug_context ctx)
Initialise a recursive mutex variable Initialises a 'recursive' mutex which might be locked by the sa...
Definition recmutex.c:32
static LumieraRecmutex lumiera_recmutex_timedlock(LumieraRecmutex self, const struct timespec *timeout, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Definition recmutex.h:161
LumieraRecmutex lumiera_recmutex_destroy(LumieraRecmutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a recursive mutex variable.
Definition recmutex.c:53
static LumieraRecmutex lumiera_recmutex_trylock(LumieraRecmutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Definition recmutex.h:132
static void lumiera_recmutex_unlock(LumieraRecmutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Definition recmutex.h:191
lumiera_recmutex * LumieraRecmutex
Definition recmutex.h:85
static LumieraRecmutex lumiera_recmutex_lock(LumieraRecmutex self, struct nobug_flag *flag, struct nobug_resource_user **handle, const struct nobug_context ctx)
Definition recmutex.h:111
Mutex state handle for locked code sections.
Recursive Mutex.
Definition recmutex.h:80
pthread_mutex_t recmutex
Definition recmutex.h:81