initial commit
[goodguy/history.git] / cinelerra-5.0 / guicast / condition.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 "condition.h"
26
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <sys/time.h>
31 #include <unistd.h>
32
33 Condition::Condition(int init_value, const char *title, int is_binary)
34 {
35         this->is_binary = is_binary;
36         this->title = title;
37         pthread_mutex_init(&mutex, 0);
38         pthread_cond_init(&cond, NULL);
39         this->value = this->init_value = init_value;
40 }
41
42 Condition:: ~Condition()
43 {
44         pthread_cond_destroy(&cond);
45         pthread_mutex_destroy(&mutex);
46 #ifndef NO_GUICAST
47         UNSET_ALL_LOCKS(this);
48 #endif
49 }
50
51 void Condition::reset()
52 {
53         pthread_cond_destroy(&cond);
54         pthread_mutex_destroy(&mutex);
55         pthread_mutex_init(&mutex, 0);
56         pthread_cond_init(&cond, NULL);
57         value = init_value;
58 }
59
60 void Condition::lock(const char *location)
61 {
62 #ifndef NO_GUICAST
63         SET_LOCK(this, title, location);
64 #endif
65         pthread_mutex_lock(&mutex);
66         while(value <= 0) pthread_cond_wait(&cond, &mutex);
67 #ifndef NO_GUICAST
68         UNSET_LOCK2
69 #endif
70         if(is_binary)
71                 value = 0;
72         else
73                 value--;
74         pthread_mutex_unlock(&mutex);
75 }
76
77 void Condition::unlock()
78 {
79 // The lock trace is created and removed by the acquirer
80 //#ifndef NO_GUICAST
81 //      UNSET_LOCK(this);
82 //#endif
83         pthread_mutex_lock(&mutex);
84         if(is_binary)
85                 value = 1;
86         else
87                 value++;
88         pthread_cond_signal(&cond);
89         pthread_mutex_unlock(&mutex);
90 }
91
92 int Condition::timed_lock(int microseconds, const char *location)
93 {
94         int result = 0;
95
96 #ifndef NO_GUICAST
97         SET_LOCK(this, title, location);
98 #endif
99         pthread_mutex_lock(&mutex);
100
101         struct timeval now;
102         gettimeofday(&now, 0);
103 #if 1
104         struct timespec timeout;
105         timeout.tv_sec = now.tv_sec + microseconds / 1000000;
106         timeout.tv_nsec = now.tv_usec * 1000 + (microseconds % 1000000) * 1000;
107         while(value <= 0 && result != ETIMEDOUT)
108         {
109                 result = pthread_cond_timedwait(&cond, &mutex, &timeout);
110         }
111
112         if( result )
113                 result = result == ETIMEDOUT ? 1 : -1;
114
115 #else
116         struct timeval timeout;
117         int64_t timeout_msec = ((int64_t)microseconds / 1000);
118 // This is based on the most common frame rate since it's mainly used in
119 // recording.
120         while( value <= 0 && !result ) {
121                 pthread_mutex_unlock(&mutex);
122                 usleep(20000);
123                 gettimeofday(&timeout, 0);
124                 timeout.tv_usec -= now.tv_usec;
125                 timeout.tv_sec -= now.tv_sec;
126                 pthread_mutex_lock(&mutex);
127                 if( value > 0 ) break;
128                 if( (int64_t)timeout.tv_sec * 1000 +
129                     (int64_t)timeout.tv_usec / 1000 > timeout_msec )
130                         result = 1;
131         }
132 #endif
133
134 #ifndef NO_GUICAST
135         UNSET_LOCK2
136 #endif
137 //printf("Condition::timed_lock 2 %d %s %s\n", result, title, location);
138         if( !result ) {
139                 if(is_binary)
140                         value = 0;
141                 else
142                         --value;
143         }
144         pthread_mutex_unlock(&mutex);
145         return result;
146 }
147
148
149 int Condition::get_value()
150 {
151         return value;
152 }