9b993fe812fe9aa08c9bf9806b8d03e93b36de62
[goodguy/history.git] / cinelerra-5.0 / guicast / mutex.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #ifndef NO_GUICAST
23 #include "bcsignals.h"
24 #endif
25 #include "mutex.h"
26
27 Mutex::Mutex(const char *title, int recursive)
28 {
29         this->title = title;
30         pthread_mutexattr_t attr;
31         pthread_mutexattr_init(&attr);
32         pthread_mutex_init(&mutex, &attr);
33         pthread_mutex_init(&recursive_lock, &attr);
34         count = 0;
35         this->recursive = recursive;
36         thread_id = 0;
37         thread_id_valid = 0;
38 }
39
40 Mutex::~Mutex()
41 {
42         pthread_mutex_destroy(&mutex);
43         pthread_mutex_destroy(&recursive_lock);
44 #ifndef NO_GUICAST
45         UNSET_ALL_LOCKS(this);
46 #endif
47 }
48
49 int Mutex::lock(const char *location)
50 {
51 // Test recursive owner and give up if we already own it
52         if(recursive)
53         {
54                 pthread_mutex_lock(&recursive_lock);
55                 if(thread_id_valid && pthread_self() == thread_id)
56                 {
57                         count++;
58                         pthread_mutex_unlock(&recursive_lock);
59                         return 0;
60                 }
61                 pthread_mutex_unlock(&recursive_lock);
62         }
63
64
65 #ifndef NO_GUICAST
66         SET_LOCK(this, title, location);
67 #endif
68         if(pthread_mutex_lock(&mutex)) perror("Mutex::lock");
69
70
71
72 // Update recursive status for the first lock
73         if(recursive)
74         {
75                 pthread_mutex_lock(&recursive_lock);
76                 count = 1;
77                 thread_id = pthread_self();
78                 thread_id_valid = 1;
79                 pthread_mutex_unlock(&recursive_lock);
80         }
81         else
82         {
83                 count = 1;
84         }
85
86
87 #ifndef NO_GUICAST
88         SET_LOCK2
89 #endif
90         return 0;
91 }
92
93 int Mutex::unlock()
94 {
95 // Remove from recursive status
96         if(recursive)
97         {
98                 pthread_mutex_lock(&recursive_lock);
99                 count--;
100 // Still locked
101                 if(count > 0)
102                 {
103                         pthread_mutex_unlock(&recursive_lock);
104                         return 0;
105                 }
106 // Not owned anymore
107                 thread_id = 0;
108                 thread_id_valid = 0;
109                 pthread_mutex_unlock(&recursive_lock);
110         }
111         else
112                 count = 0;
113
114
115 #ifndef NO_GUICAST
116         UNSET_LOCK(this);
117 #endif
118
119         if(pthread_mutex_unlock(&mutex)) perror("Mutex::unlock");
120         return 0;
121 }
122
123 int Mutex::trylock(const char *location)
124 {
125         int ret = pthread_mutex_trylock(&mutex);
126         if( ret ) return ret;
127
128 // Update recursive status for the first lock
129         if(recursive) {
130                 pthread_mutex_lock(&recursive_lock);
131                 count = 1;
132                 thread_id = pthread_self();
133                 thread_id_valid = 1;
134                 pthread_mutex_unlock(&recursive_lock);
135         }
136         else
137                 count = 1;
138
139 #ifndef NO_GUICAST
140         SET_LOCK(this, title, location);
141         SET_LOCK2
142 #endif
143         return 0;
144 }
145
146 int Mutex::is_locked()
147 {
148         return count;
149 }
150
151 int Mutex::reset()
152 {
153         pthread_mutex_destroy(&mutex);
154         pthread_mutexattr_t attr;
155         pthread_mutexattr_init(&attr);
156         pthread_mutex_init(&mutex, &attr);
157         count = 0;
158         thread_id = 0;
159         thread_id_valid = 0;
160 #ifndef NO_GUICAST
161         UNSET_ALL_LOCKS(this)
162 #endif
163         return 0;
164 }