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