improvements/fixes from MatN and Andrew related to AppImage and batch render
[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         unset_owner();
56         value = init_value;
57         trace = 0;
58 }
59
60 void Condition::lock(const char *location)
61 {
62         SET_LOCK(this, title, location);
63         pthread_mutex_lock(&mutex);
64         while(value <= 0) pthread_cond_wait(&cond, &mutex);
65         UNSET_LOCK2
66         if(is_binary)
67                 value = 0;
68         else
69                 value--;
70         if( !value )
71                 set_owner();
72         pthread_mutex_unlock(&mutex);
73 }
74
75 void Condition::unlock()
76 {
77 // The lock trace is created and removed by the acquirer
78 //      UNSET_LOCK(this);
79         pthread_mutex_lock(&mutex);
80         if(is_binary)
81                 value = 1;
82         else
83                 value++;
84         unset_owner();
85         pthread_cond_signal(&cond);
86         pthread_mutex_unlock(&mutex);
87 }
88
89 int Condition::timed_lock(int microseconds, const char *location)
90 {
91         int result = 0;
92
93         SET_LOCK(this, title, location);
94         pthread_mutex_lock(&mutex);
95
96         struct timeval now;
97         gettimeofday(&now, 0);
98 #if 1
99         int64_t nsec = now.tv_usec * 1000 + (microseconds % 1000000) * 1000;
100         int64_t sec = nsec / 1000000000;  nsec %= 1000000000;
101         sec += now.tv_sec + microseconds / 1000000;
102         struct timespec timeout;  timeout.tv_sec = sec;   timeout.tv_nsec = nsec;
103         while( value <= 0 && result != ETIMEDOUT ) {
104                 result = pthread_cond_timedwait(&cond, &mutex, &timeout);
105         }
106
107         if( result )
108                 result = result == ETIMEDOUT ? 1 : -1;
109
110 #else
111         struct timeval timeout;
112         int64_t timeout_msec = ((int64_t)microseconds / 1000);
113 // This is based on the most common frame rate since it's mainly used in
114 // recording.
115         while( value <= 0 && !result ) {
116                 pthread_mutex_unlock(&mutex);
117                 usleep(20000);
118                 gettimeofday(&timeout, 0);
119                 timeout.tv_usec -= now.tv_usec;
120                 timeout.tv_sec -= now.tv_sec;
121                 pthread_mutex_lock(&mutex);
122                 if( value > 0 ) break;
123                 if( (int64_t)timeout.tv_sec * 1000 +
124                     (int64_t)timeout.tv_usec / 1000 > timeout_msec )
125                         result = 1;
126         }
127 #endif
128
129         UNSET_LOCK2
130 //printf("Condition::timed_lock 2 %d %s %s\n", result, title, location);
131         if( !result ) {
132                 if(is_binary)
133                         value = 0;
134                 else
135                         --value;
136         }
137         if( !value )
138                 set_owner();
139         pthread_mutex_unlock(&mutex);
140         return result;
141 }
142
143
144 int Condition::get_value()
145 {
146         return value;
147 }