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