1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "Channel.h"
22
23#include <timer/Timer.h>
24
25namespace love
26{
27namespace thread
28{
29
30love::Type Channel::type("Channel", &Object::type);
31
32Channel::Channel()
33 : sent(0)
34 , received(0)
35{
36}
37
38Channel::~Channel()
39{
40}
41
42uint64 Channel::push(const Variant &var)
43{
44 Lock l(mutex);
45
46 queue.push(var);
47 cond->broadcast();
48
49 return ++sent;
50}
51
52bool Channel::supply(const Variant &var)
53{
54 Lock l(mutex);
55 uint64 id = push(var);
56
57 while (received < id)
58 cond->wait(mutex);
59
60 return true;
61}
62
63bool Channel::supply(const Variant &var, double timeout)
64{
65 Lock l(mutex);
66 uint64 id = push(var);
67
68 while (timeout >= 0)
69 {
70 if (received >= id)
71 return true;
72
73 double start = love::timer::Timer::getTime();
74 cond->wait(mutex, timeout*1000);
75 double stop = love::timer::Timer::getTime();
76
77 timeout -= (stop-start);
78 }
79
80 return false;
81}
82
83bool Channel::pop(Variant *var)
84{
85 Lock l(mutex);
86
87 if (queue.empty())
88 return false;
89
90 *var = queue.front();
91 queue.pop();
92
93 received++;
94 cond->broadcast();
95
96 return true;
97}
98
99bool Channel::demand(Variant *var)
100{
101 Lock l(mutex);
102
103 while (!pop(var))
104 cond->wait(mutex);
105
106 return true;
107}
108
109bool Channel::demand(Variant *var, double timeout)
110{
111 Lock l(mutex);
112
113 while (timeout >= 0)
114 {
115 if (pop(var))
116 return true;
117
118 double start = love::timer::Timer::getTime();
119 cond->wait(mutex, timeout*1000);
120 double stop = love::timer::Timer::getTime();
121
122 timeout -= (stop-start);
123 }
124
125 return false;
126}
127
128bool Channel::peek(Variant *var)
129{
130 Lock l(mutex);
131
132 if (queue.empty())
133 return false;
134
135 *var = queue.front();
136 return true;
137}
138
139int Channel::getCount() const
140{
141 Lock l(mutex);
142 return (int) queue.size();
143}
144
145bool Channel::hasRead(uint64 id) const
146{
147 Lock l(mutex);
148 return received >= id;
149}
150
151void Channel::clear()
152{
153 Lock l(mutex);
154
155 // We're already empty.
156 if (queue.empty())
157 return;
158
159 while (!queue.empty())
160 queue.pop();
161
162 // Finish all the supply waits
163 received = sent;
164 cond->broadcast();
165}
166
167void Channel::lockMutex()
168{
169 mutex->lock();
170}
171
172void Channel::unlockMutex()
173{
174 mutex->unlock();
175}
176
177} // thread
178} // love
179