1 /* Copyright (c) 2012-2016, The Linux Foundation. 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 // System dependencies
31 #include <string.h>
32 #include <utils/Errors.h>
33
34 // Camera dependencies
35 #include "QCameraQueue.h"
36
37 extern "C" {
38 #include "mm_camera_dbg.h"
39 }
40
41 namespace qcamera {
42
43 /*===========================================================================
44 * FUNCTION : QCameraQueue
45 *
46 * DESCRIPTION: default constructor of QCameraQueue
47 *
48 * PARAMETERS : None
49 *
50 * RETURN : None
51 *==========================================================================*/
QCameraQueue()52 QCameraQueue::QCameraQueue()
53 {
54 pthread_mutex_init(&m_lock, NULL);
55 cam_list_init(&m_head.list);
56 m_size = 0;
57 m_dataFn = NULL;
58 m_userData = NULL;
59 m_active = true;
60 }
61
62 /*===========================================================================
63 * FUNCTION : QCameraQueue
64 *
65 * DESCRIPTION: constructor of QCameraQueue
66 *
67 * PARAMETERS :
68 * @data_rel_fn : function ptr to release node data internal resource
69 * @user_data : user data ptr
70 *
71 * RETURN : None
72 *==========================================================================*/
QCameraQueue(release_data_fn data_rel_fn,void * user_data)73 QCameraQueue::QCameraQueue(release_data_fn data_rel_fn, void *user_data)
74 {
75 pthread_mutex_init(&m_lock, NULL);
76 cam_list_init(&m_head.list);
77 m_size = 0;
78 m_dataFn = data_rel_fn;
79 m_userData = user_data;
80 m_active = true;
81 }
82
83 /*===========================================================================
84 * FUNCTION : ~QCameraQueue
85 *
86 * DESCRIPTION: deconstructor of QCameraQueue
87 *
88 * PARAMETERS : None
89 *
90 * RETURN : None
91 *==========================================================================*/
~QCameraQueue()92 QCameraQueue::~QCameraQueue()
93 {
94 flush();
95 pthread_mutex_destroy(&m_lock);
96 }
97
98 /*===========================================================================
99 * FUNCTION : init
100 *
101 * DESCRIPTION: Put the queue to active state (ready to enqueue and dequeue)
102 *
103 * PARAMETERS : None
104 *
105 * RETURN : None
106 *==========================================================================*/
init()107 void QCameraQueue::init()
108 {
109 pthread_mutex_lock(&m_lock);
110 m_active = true;
111 pthread_mutex_unlock(&m_lock);
112 }
113
114 /*===========================================================================
115 * FUNCTION : isEmpty
116 *
117 * DESCRIPTION: return if the queue is empty or not
118 *
119 * PARAMETERS : None
120 *
121 * RETURN : true -- queue is empty; false -- not empty
122 *==========================================================================*/
isEmpty()123 bool QCameraQueue::isEmpty()
124 {
125 bool flag = true;
126 pthread_mutex_lock(&m_lock);
127 if (m_size > 0) {
128 flag = false;
129 }
130 pthread_mutex_unlock(&m_lock);
131 return flag;
132 }
133
134 /*===========================================================================
135 * FUNCTION : enqueue
136 *
137 * DESCRIPTION: enqueue data into the queue
138 *
139 * PARAMETERS :
140 * @data : data to be enqueued
141 *
142 * RETURN : true -- success; false -- failed
143 *==========================================================================*/
enqueue(void * data)144 bool QCameraQueue::enqueue(void *data)
145 {
146 bool rc;
147 camera_q_node *node =
148 (camera_q_node *)malloc(sizeof(camera_q_node));
149 if (NULL == node) {
150 LOGE("No memory for camera_q_node");
151 return false;
152 }
153
154 memset(node, 0, sizeof(camera_q_node));
155 node->data = data;
156
157 pthread_mutex_lock(&m_lock);
158 if (m_active) {
159 cam_list_add_tail_node(&node->list, &m_head.list);
160 m_size++;
161 rc = true;
162 } else {
163 free(node);
164 rc = false;
165 }
166 pthread_mutex_unlock(&m_lock);
167 return rc;
168 }
169
170 /*===========================================================================
171 * FUNCTION : enqueueWithPriority
172 *
173 * DESCRIPTION: enqueue data into queue with priority, will insert into the
174 * head of the queue
175 *
176 * PARAMETERS :
177 * @data : data to be enqueued
178 *
179 * RETURN : true -- success; false -- failed
180 *==========================================================================*/
enqueueWithPriority(void * data)181 bool QCameraQueue::enqueueWithPriority(void *data)
182 {
183 bool rc;
184 camera_q_node *node =
185 (camera_q_node *)malloc(sizeof(camera_q_node));
186 if (NULL == node) {
187 LOGE("No memory for camera_q_node");
188 return false;
189 }
190
191 memset(node, 0, sizeof(camera_q_node));
192 node->data = data;
193
194 pthread_mutex_lock(&m_lock);
195 if (m_active) {
196 struct cam_list *p_next = m_head.list.next;
197
198 m_head.list.next = &node->list;
199 p_next->prev = &node->list;
200 node->list.next = p_next;
201 node->list.prev = &m_head.list;
202
203 m_size++;
204 rc = true;
205 } else {
206 free(node);
207 rc = false;
208 }
209 pthread_mutex_unlock(&m_lock);
210 return rc;
211 }
212
213 /*===========================================================================
214 * FUNCTION : peek
215 *
216 * DESCRIPTION: return the head element without removing it
217 *
218 * PARAMETERS : None
219 *
220 * RETURN : data ptr. NULL if not any data in the queue.
221 *==========================================================================*/
peek()222 void* QCameraQueue::peek()
223 {
224 camera_q_node* node = NULL;
225 void* data = NULL;
226 struct cam_list *head = NULL;
227 struct cam_list *pos = NULL;
228
229 pthread_mutex_lock(&m_lock);
230 if (m_active) {
231 head = &m_head.list;
232 pos = head->next;
233 if (pos != head) {
234 node = member_of(pos, camera_q_node, list);
235 }
236 }
237 pthread_mutex_unlock(&m_lock);
238
239 if (NULL != node) {
240 data = node->data;
241 }
242
243 return data;
244 }
245
246 /*===========================================================================
247 * FUNCTION : dequeue
248 *
249 * DESCRIPTION: dequeue data from the queue
250 *
251 * PARAMETERS :
252 * @bFromHead : if true, dequeue from the head
253 * if false, dequeue from the tail
254 *
255 * RETURN : data ptr. NULL if not any data in the queue.
256 *==========================================================================*/
dequeue(bool bFromHead)257 void* QCameraQueue::dequeue(bool bFromHead)
258 {
259 camera_q_node* node = NULL;
260 void* data = NULL;
261 struct cam_list *head = NULL;
262 struct cam_list *pos = NULL;
263
264 pthread_mutex_lock(&m_lock);
265 if (m_active) {
266 head = &m_head.list;
267 if (bFromHead) {
268 pos = head->next;
269 } else {
270 pos = head->prev;
271 }
272 if (pos != head) {
273 node = member_of(pos, camera_q_node, list);
274 cam_list_del_node(&node->list);
275 m_size--;
276 }
277 }
278 pthread_mutex_unlock(&m_lock);
279
280 if (NULL != node) {
281 data = node->data;
282 free(node);
283 }
284
285 return data;
286 }
287
288 /*===========================================================================
289 * FUNCTION : dequeue
290 *
291 * DESCRIPTION: dequeue data from the queue
292 *
293 * PARAMETERS :
294 * @match : matching function callback
295 * @match_data : the actual data to be matched
296 *
297 * RETURN : data ptr. NULL if not any data in the queue.
298 *==========================================================================*/
dequeue(match_fn_data match,void * match_data)299 void* QCameraQueue::dequeue(match_fn_data match, void *match_data){
300 camera_q_node* node = NULL;
301 struct cam_list *head = NULL;
302 struct cam_list *pos = NULL;
303 void* data = NULL;
304
305 if ( NULL == match || NULL == match_data ) {
306 return NULL;
307 }
308
309 pthread_mutex_lock(&m_lock);
310 if (m_active) {
311 head = &m_head.list;
312 pos = head->next;
313
314 while(pos != head) {
315 node = member_of(pos, camera_q_node, list);
316 pos = pos->next;
317 if (NULL != node) {
318 if ( match(node->data, m_userData, match_data) ) {
319 cam_list_del_node(&node->list);
320 m_size--;
321 data = node->data;
322 free(node);
323 pthread_mutex_unlock(&m_lock);
324 return data;
325 }
326 }
327 }
328 }
329 pthread_mutex_unlock(&m_lock);
330 return NULL;
331 }
332
333 /*===========================================================================
334 * FUNCTION : flush
335 *
336 * DESCRIPTION: flush all nodes from the queue, queue will be empty after this
337 * operation.
338 *
339 * PARAMETERS : None
340 *
341 * RETURN : None
342 *==========================================================================*/
flush()343 void QCameraQueue::flush(){
344 camera_q_node* node = NULL;
345 struct cam_list *head = NULL;
346 struct cam_list *pos = NULL;
347
348 pthread_mutex_lock(&m_lock);
349 if (m_active) {
350 head = &m_head.list;
351 pos = head->next;
352
353 while(pos != head) {
354 node = member_of(pos, camera_q_node, list);
355 pos = pos->next;
356 cam_list_del_node(&node->list);
357 m_size--;
358
359 if (NULL != node->data) {
360 if (m_dataFn) {
361 m_dataFn(node->data, m_userData);
362 }
363 free(node->data);
364 }
365 free(node);
366
367 }
368 m_size = 0;
369 m_active = false;
370 }
371 pthread_mutex_unlock(&m_lock);
372 }
373
374 /*===========================================================================
375 * FUNCTION : flushNodes
376 *
377 * DESCRIPTION: flush only specific nodes, depending on
378 * the given matching function.
379 *
380 * PARAMETERS :
381 * @match : matching function
382 *
383 * RETURN : None
384 *==========================================================================*/
flushNodes(match_fn match)385 void QCameraQueue::flushNodes(match_fn match){
386 camera_q_node* node = NULL;
387 struct cam_list *head = NULL;
388 struct cam_list *pos = NULL;
389
390 if ( NULL == match ) {
391 return;
392 }
393
394 pthread_mutex_lock(&m_lock);
395 if (m_active) {
396 head = &m_head.list;
397 pos = head->next;
398
399 while(pos != head) {
400 node = member_of(pos, camera_q_node, list);
401 pos = pos->next;
402 if ( match(node->data, m_userData) ) {
403 cam_list_del_node(&node->list);
404 m_size--;
405
406 if (NULL != node->data) {
407 if (m_dataFn) {
408 m_dataFn(node->data, m_userData);
409 }
410 free(node->data);
411 }
412 free(node);
413 }
414 }
415 }
416 pthread_mutex_unlock(&m_lock);
417 }
418
419 /*===========================================================================
420 * FUNCTION : flushNodes
421 *
422 * DESCRIPTION: flush only specific nodes, depending on
423 * the given matching function.
424 *
425 * PARAMETERS :
426 * @match : matching function
427 *
428 * RETURN : None
429 *==========================================================================*/
flushNodes(match_fn_data match,void * match_data)430 void QCameraQueue::flushNodes(match_fn_data match, void *match_data){
431 camera_q_node* node = NULL;
432 struct cam_list *head = NULL;
433 struct cam_list *pos = NULL;
434
435 if ( NULL == match ) {
436 return;
437 }
438
439 pthread_mutex_lock(&m_lock);
440 if (m_active) {
441 head = &m_head.list;
442 pos = head->next;
443
444 while(pos != head) {
445 node = member_of(pos, camera_q_node, list);
446 pos = pos->next;
447 if ( match(node->data, m_userData, match_data) ) {
448 cam_list_del_node(&node->list);
449 m_size--;
450
451 if (NULL != node->data) {
452 if (m_dataFn) {
453 m_dataFn(node->data, m_userData);
454 }
455 free(node->data);
456 }
457 free(node);
458 }
459 }
460 }
461 pthread_mutex_unlock(&m_lock);
462 }
463
464 }; // namespace qcamera
465