1 /* Copyright (c) 2012, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include <utils/Errors.h>
31 #include <utils/Log.h>
32 #include "QCameraQueue.h"
33
34 namespace qcamera {
35
36 /*===========================================================================
37 * FUNCTION : QCameraQueue
38 *
39 * DESCRIPTION: default constructor of QCameraQueue
40 *
41 * PARAMETERS : None
42 *
43 * RETURN : None
44 *==========================================================================*/
QCameraQueue()45 QCameraQueue::QCameraQueue()
46 {
47 pthread_mutex_init(&m_lock, NULL);
48 cam_list_init(&m_head.list);
49 m_size = 0;
50 m_dataFn = NULL;
51 m_userData = NULL;
52 m_active = true;
53 }
54
55 /*===========================================================================
56 * FUNCTION : QCameraQueue
57 *
58 * DESCRIPTION: constructor of QCameraQueue
59 *
60 * PARAMETERS :
61 * @data_rel_fn : function ptr to release node data internal resource
62 * @user_data : user data ptr
63 *
64 * RETURN : None
65 *==========================================================================*/
QCameraQueue(release_data_fn data_rel_fn,void * user_data)66 QCameraQueue::QCameraQueue(release_data_fn data_rel_fn, void *user_data)
67 {
68 pthread_mutex_init(&m_lock, NULL);
69 cam_list_init(&m_head.list);
70 m_size = 0;
71 m_dataFn = data_rel_fn;
72 m_userData = user_data;
73 m_active = true;
74 }
75
76 /*===========================================================================
77 * FUNCTION : ~QCameraQueue
78 *
79 * DESCRIPTION: deconstructor of QCameraQueue
80 *
81 * PARAMETERS : None
82 *
83 * RETURN : None
84 *==========================================================================*/
~QCameraQueue()85 QCameraQueue::~QCameraQueue()
86 {
87 flush();
88 pthread_mutex_destroy(&m_lock);
89 }
90
91 /*===========================================================================
92 * FUNCTION : init
93 *
94 * DESCRIPTION: Put the queue to active state (ready to enqueue and dequeue)
95 *
96 * PARAMETERS : None
97 *
98 * RETURN : None
99 *==========================================================================*/
init()100 void QCameraQueue::init()
101 {
102 pthread_mutex_lock(&m_lock);
103 m_active = true;
104 pthread_mutex_unlock(&m_lock);
105 }
106
107 /*===========================================================================
108 * FUNCTION : isEmpty
109 *
110 * DESCRIPTION: return if the queue is empty or not
111 *
112 * PARAMETERS : None
113 *
114 * RETURN : true -- queue is empty; false -- not empty
115 *==========================================================================*/
isEmpty()116 bool QCameraQueue::isEmpty()
117 {
118 bool flag = true;
119 pthread_mutex_lock(&m_lock);
120 if (m_size > 0) {
121 flag = false;
122 }
123 pthread_mutex_unlock(&m_lock);
124 return flag;
125 }
126
127 /*===========================================================================
128 * FUNCTION : enqueue
129 *
130 * DESCRIPTION: enqueue data into the queue
131 *
132 * PARAMETERS :
133 * @data : data to be enqueued
134 *
135 * RETURN : true -- success; false -- failed
136 *==========================================================================*/
enqueue(void * data)137 bool QCameraQueue::enqueue(void *data)
138 {
139 bool rc;
140 camera_q_node *node =
141 (camera_q_node *)malloc(sizeof(camera_q_node));
142 if (NULL == node) {
143 ALOGE("%s: No memory for camera_q_node", __func__);
144 return false;
145 }
146
147 memset(node, 0, sizeof(camera_q_node));
148 node->data = data;
149
150 pthread_mutex_lock(&m_lock);
151 if (m_active) {
152 cam_list_add_tail_node(&node->list, &m_head.list);
153 m_size++;
154 rc = true;
155 } else {
156 free(node);
157 rc = false;
158 }
159 pthread_mutex_unlock(&m_lock);
160 return rc;
161 }
162
163 /*===========================================================================
164 * FUNCTION : enqueueWithPriority
165 *
166 * DESCRIPTION: enqueue data into queue with priority, will insert into the
167 * head of the queue
168 *
169 * PARAMETERS :
170 * @data : data to be enqueued
171 *
172 * RETURN : true -- success; false -- failed
173 *==========================================================================*/
enqueueWithPriority(void * data)174 bool QCameraQueue::enqueueWithPriority(void *data)
175 {
176 bool rc;
177 camera_q_node *node =
178 (camera_q_node *)malloc(sizeof(camera_q_node));
179 if (NULL == node) {
180 ALOGE("%s: No memory for camera_q_node", __func__);
181 return false;
182 }
183
184 memset(node, 0, sizeof(camera_q_node));
185 node->data = data;
186
187 pthread_mutex_lock(&m_lock);
188 if (m_active) {
189 struct cam_list *p_next = m_head.list.next;
190
191 m_head.list.next = &node->list;
192 p_next->prev = &node->list;
193 node->list.next = p_next;
194 node->list.prev = &m_head.list;
195
196 m_size++;
197 rc = true;
198 } else {
199 free(node);
200 rc = false;
201 }
202 pthread_mutex_unlock(&m_lock);
203 return rc;
204 }
205
206 /*===========================================================================
207 * FUNCTION : peek
208 *
209 * DESCRIPTION: return the head element without removing it
210 *
211 * PARAMETERS : None
212 *
213 * RETURN : data ptr. NULL if not any data in the queue.
214 *==========================================================================*/
peek()215 void* QCameraQueue::peek()
216 {
217 camera_q_node* node = NULL;
218 void* data = NULL;
219 struct cam_list *head = NULL;
220 struct cam_list *pos = NULL;
221
222 pthread_mutex_lock(&m_lock);
223 if (m_active) {
224 head = &m_head.list;
225 pos = head->next;
226 if (pos != head) {
227 node = member_of(pos, camera_q_node, list);
228 }
229 }
230 pthread_mutex_unlock(&m_lock);
231
232 if (NULL != node) {
233 data = node->data;
234 }
235
236 return data;
237 }
238
239 /*===========================================================================
240 * FUNCTION : dequeue
241 *
242 * DESCRIPTION: dequeue data from the queue
243 *
244 * PARAMETERS :
245 * @bFromHead : if true, dequeue from the head
246 * if false, dequeue from the tail
247 *
248 * RETURN : data ptr. NULL if not any data in the queue.
249 *==========================================================================*/
dequeue(bool bFromHead)250 void* QCameraQueue::dequeue(bool bFromHead)
251 {
252 camera_q_node* node = NULL;
253 void* data = NULL;
254 struct cam_list *head = NULL;
255 struct cam_list *pos = NULL;
256
257 pthread_mutex_lock(&m_lock);
258 if (m_active) {
259 head = &m_head.list;
260 if (bFromHead) {
261 pos = head->next;
262 } else {
263 pos = head->prev;
264 }
265 if (pos != head) {
266 node = member_of(pos, camera_q_node, list);
267 cam_list_del_node(&node->list);
268 m_size--;
269 }
270 }
271 pthread_mutex_unlock(&m_lock);
272
273 if (NULL != node) {
274 data = node->data;
275 free(node);
276 }
277
278 return data;
279 }
280
281 /*===========================================================================
282 * FUNCTION : flush
283 *
284 * DESCRIPTION: flush all nodes from the queue, queue will be empty after this
285 * operation.
286 *
287 * PARAMETERS : None
288 *
289 * RETURN : None
290 *==========================================================================*/
flush()291 void QCameraQueue::flush(){
292 camera_q_node* node = NULL;
293 struct cam_list *head = NULL;
294 struct cam_list *pos = NULL;
295
296 pthread_mutex_lock(&m_lock);
297 if (m_active) {
298 head = &m_head.list;
299 pos = head->next;
300
301 while(pos != head) {
302 node = member_of(pos, camera_q_node, list);
303 pos = pos->next;
304 cam_list_del_node(&node->list);
305 m_size--;
306
307 if (NULL != node->data) {
308 if (m_dataFn) {
309 m_dataFn(node->data, m_userData);
310 }
311 free(node->data);
312 }
313 free(node);
314
315 }
316 m_size = 0;
317 m_active = false;
318 }
319 pthread_mutex_unlock(&m_lock);
320 }
321
322 /*===========================================================================
323 * FUNCTION : flushNodes
324 *
325 * DESCRIPTION: flush only specific nodes, depending on
326 * the given matching function.
327 *
328 * PARAMETERS :
329 * @match : matching function
330 *
331 * RETURN : None
332 *==========================================================================*/
flushNodes(match_fn match)333 void QCameraQueue::flushNodes(match_fn match){
334 camera_q_node* node = NULL;
335 struct cam_list *head = NULL;
336 struct cam_list *pos = NULL;
337
338 if ( NULL == match ) {
339 return;
340 }
341
342 pthread_mutex_lock(&m_lock);
343 if (m_active) {
344 head = &m_head.list;
345 pos = head->next;
346
347 while(pos != head) {
348 node = member_of(pos, camera_q_node, list);
349 pos = pos->next;
350 if ( match(node->data, m_userData) ) {
351 cam_list_del_node(&node->list);
352 m_size--;
353
354 if (NULL != node->data) {
355 if (m_dataFn) {
356 m_dataFn(node->data, m_userData);
357 }
358 free(node->data);
359 }
360 free(node);
361 }
362 }
363 }
364 pthread_mutex_unlock(&m_lock);
365 }
366
367 /*===========================================================================
368 * FUNCTION : flushNodes
369 *
370 * DESCRIPTION: flush only specific nodes, depending on
371 * the given matching function.
372 *
373 * PARAMETERS :
374 * @match : matching function
375 *
376 * RETURN : None
377 *==========================================================================*/
flushNodes(match_fn_data match,void * match_data)378 void QCameraQueue::flushNodes(match_fn_data match, void *match_data){
379 camera_q_node* node = NULL;
380 struct cam_list *head = NULL;
381 struct cam_list *pos = NULL;
382
383 if ( NULL == match ) {
384 return;
385 }
386
387 pthread_mutex_lock(&m_lock);
388 if (m_active) {
389 head = &m_head.list;
390 pos = head->next;
391
392 while(pos != head) {
393 node = member_of(pos, camera_q_node, list);
394 pos = pos->next;
395 if ( match(node->data, m_userData, match_data) ) {
396 cam_list_del_node(&node->list);
397 m_size--;
398
399 if (NULL != node->data) {
400 if (m_dataFn) {
401 m_dataFn(node->data, m_userData);
402 }
403 free(node->data);
404 }
405 free(node);
406 }
407 }
408 }
409 pthread_mutex_unlock(&m_lock);
410 }
411
412 }; // namespace qcamera
413