Merged trunk and subtype.
[cacao.git] / src / threads / posix / mutex-posix.hpp
1 /* src/threads/posix/mutex-posix.hpp - POSIX mutual exclusion functions
2
3    Copyright (C) 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #ifndef _MUTEX_POSIX_HPP
28 #define _MUTEX_POSIX_HPP
29
30 #include "config.h"
31
32 #include <pthread.h>
33
34
35 #ifdef __cplusplus
36
37 /**
38  * POSIX implementation of a mutex.
39  */
40 class Mutex {
41 private:
42         // POSIX mutex structure.
43         pthread_mutex_t     _mutex;
44         pthread_mutexattr_t _attr;
45
46         // Condition class needs to access _mutex for wait() and
47         // timedwait().
48         friend class Condition;
49         
50 public:
51         inline Mutex();
52         inline ~Mutex();
53
54         inline void lock();
55         inline void unlock();
56 };
57
58 #else
59
60 // Forward typedefs
61 typedef struct Mutex Mutex;
62
63 #endif
64
65
66 // Includes.
67 #include "vm/vm.hpp"
68
69
70 #ifdef __cplusplus
71
72 /**
73  * Initializes the given mutex object and checks for errors.
74  */
75 inline Mutex::Mutex()
76 {
77         int result = pthread_mutexattr_init(&_attr);
78
79         if (result != 0) {
80                 VM::get_current()->abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_init failed");
81         }
82
83         result = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
84
85         if (result != 0) {
86                 VM::get_current()->abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_settype failed");
87         }
88
89         result = pthread_mutex_init(&_mutex, &_attr);
90
91         if (result != 0) {
92                 VM::get_current()->abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
93         }
94 }
95
96
97 /**
98  * Destroys the given mutex object and checks for errors.
99  */
100 inline Mutex::~Mutex()
101 {
102         int result = pthread_mutexattr_destroy(&_attr);
103
104         if (result != 0) {
105                 VM::get_current()->abort_errnum(result, "Mutex::~Mutex(): pthread_mutexattr_destroy failed");
106         }
107
108         result = pthread_mutex_destroy(&_mutex);
109
110         if (result != 0) {
111                 VM::get_current()->abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
112         }
113 }
114
115
116 /**
117  * Locks the given mutex object and checks for errors. If the mutex is
118  * already locked by another thread, the calling thread is suspended until
119  * the mutex is unlocked.
120  *
121  * If the mutex is already locked by the calling thread, the same applies,
122  * thus effectively causing the calling thread to deadlock. (This is because
123  * we use "fast" pthread mutexes without error checking.)
124  */
125 inline void Mutex::lock()
126 {
127         int result = pthread_mutex_lock(&_mutex);
128
129         if (result != 0) {
130                 VM::get_current()->abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
131         }
132 }
133
134
135 /**
136  * Unlocks the given mutex object and checks for errors. The mutex is
137  * assumed to be locked and owned by the calling thread.
138  */
139 inline void Mutex::unlock()
140 {
141         int result = pthread_mutex_unlock(&_mutex);
142
143         if (result != 0) {
144                 VM::get_current()->abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
145         }
146 }
147
148 #else
149
150 // This structure must have the same layout as the class above.
151 struct Mutex {
152         pthread_mutex_t     _mutex;
153         pthread_mutexattr_t _attr;
154 };
155
156 Mutex* Mutex_new();
157 void   Mutex_delete(Mutex* mutex);
158 void   Mutex_lock(Mutex* mutex);
159 void   Mutex_unlock(Mutex* mutex);
160
161 #endif
162
163 #endif /* _MUTEX_POSIX_HPP */
164
165
166 /*
167  * These are local overrides for various environment variables in Emacs.
168  * Please do not remove this and leave it at the end of the file, where
169  * Emacs will automagically detect them.
170  * ---------------------------------------------------------------------
171  * Local variables:
172  * mode: c++
173  * indent-tabs-mode: t
174  * c-basic-offset: 4
175  * tab-width: 4
176  * End:
177  * vim:noexpandtab:sw=4:ts=4:
178  */