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