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