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 }
53 
54 /*===========================================================================
55  * FUNCTION   : QCameraQueue
56  *
57  * DESCRIPTION: constructor of QCameraQueue
58  *
59  * PARAMETERS :
60  *   @data_rel_fn : function ptr to release node data internal resource
61  *   @user_data   : user data ptr
62  *
63  * RETURN     : None
64  *==========================================================================*/
QCameraQueue(release_data_fn data_rel_fn,void * user_data)65 QCameraQueue::QCameraQueue(release_data_fn data_rel_fn, void *user_data)
66 {
67     pthread_mutex_init(&m_lock, NULL);
68     cam_list_init(&m_head.list);
69     m_size = 0;
70     m_dataFn = data_rel_fn;
71     m_userData = user_data;
72 }
73 
74 /*===========================================================================
75  * FUNCTION   : ~QCameraQueue
76  *
77  * DESCRIPTION: deconstructor of QCameraQueue
78  *
79  * PARAMETERS : None
80  *
81  * RETURN     : None
82  *==========================================================================*/
~QCameraQueue()83 QCameraQueue::~QCameraQueue()
84 {
85     flush();
86     pthread_mutex_destroy(&m_lock);
87 }
88 
89 /*===========================================================================
90  * FUNCTION   : isEmpty
91  *
92  * DESCRIPTION: return if the queue is empty or not
93  *
94  * PARAMETERS : None
95  *
96  * RETURN     : true -- queue is empty; false -- not empty
97  *==========================================================================*/
isEmpty()98 bool QCameraQueue::isEmpty()
99 {
100     bool flag = true;
101     pthread_mutex_lock(&m_lock);
102     if (m_size > 0) {
103         flag = false;
104     }
105     pthread_mutex_unlock(&m_lock);
106     return flag;
107 }
108 
109 /*===========================================================================
110  * FUNCTION   : enqueue
111  *
112  * DESCRIPTION: enqueue data into the queue
113  *
114  * PARAMETERS :
115  *   @data    : data to be enqueued
116  *
117  * RETURN     : true -- success; false -- failed
118  *==========================================================================*/
enqueue(void * data)119 bool QCameraQueue::enqueue(void *data)
120 {
121     camera_q_node *node =
122         (camera_q_node *)malloc(sizeof(camera_q_node));
123     if (NULL == node) {
124         ALOGE("%s: No memory for camera_q_node", __func__);
125         return false;
126     }
127 
128     memset(node, 0, sizeof(camera_q_node));
129     node->data = data;
130 
131     pthread_mutex_lock(&m_lock);
132     cam_list_add_tail_node(&node->list, &m_head.list);
133     m_size++;
134     pthread_mutex_unlock(&m_lock);
135     return true;
136 }
137 
138 /*===========================================================================
139  * FUNCTION   : enqueueWithPriority
140  *
141  * DESCRIPTION: enqueue data into queue with priority, will insert into the
142  *              head of the queue
143  *
144  * PARAMETERS :
145  *   @data    : data to be enqueued
146  *
147  * RETURN     : true -- success; false -- failed
148  *==========================================================================*/
enqueueWithPriority(void * data)149 bool QCameraQueue::enqueueWithPriority(void *data)
150 {
151     camera_q_node *node =
152         (camera_q_node *)malloc(sizeof(camera_q_node));
153     if (NULL == node) {
154         ALOGE("%s: No memory for camera_q_node", __func__);
155         return false;
156     }
157 
158     memset(node, 0, sizeof(camera_q_node));
159     node->data = data;
160 
161     pthread_mutex_lock(&m_lock);
162     struct cam_list *p_next = m_head.list.next;
163 
164     m_head.list.next = &node->list;
165     p_next->prev = &node->list;
166     node->list.next = p_next;
167     node->list.prev = &m_head.list;
168 
169     m_size++;
170     pthread_mutex_unlock(&m_lock);
171     return true;
172 }
173 
174 /*===========================================================================
175  * FUNCTION   : dequeue
176  *
177  * DESCRIPTION: dequeue data from the queue
178  *
179  * PARAMETERS :
180  *   @bFromHead : if true, dequeue from the head
181  *                if false, dequeue from the tail
182  *
183  * RETURN     : data ptr. NULL if not any data in the queue.
184  *==========================================================================*/
dequeue(bool bFromHead)185 void* QCameraQueue::dequeue(bool bFromHead)
186 {
187     camera_q_node* node = NULL;
188     void* data = NULL;
189     struct cam_list *head = NULL;
190     struct cam_list *pos = NULL;
191 
192     pthread_mutex_lock(&m_lock);
193     head = &m_head.list;
194     if (bFromHead) {
195         pos = head->next;
196     } else {
197         pos = head->prev;
198     }
199     if (pos != head) {
200         node = member_of(pos, camera_q_node, list);
201         cam_list_del_node(&node->list);
202         m_size--;
203     }
204     pthread_mutex_unlock(&m_lock);
205 
206     if (NULL != node) {
207         data = node->data;
208         free(node);
209     }
210 
211     return data;
212 }
213 
214 /*===========================================================================
215  * FUNCTION   : flush
216  *
217  * DESCRIPTION: flush all nodes from the queue, queue will be empty after this
218  *              operation.
219  *
220  * PARAMETERS : None
221  *
222  * RETURN     : None
223  *==========================================================================*/
flush()224 void QCameraQueue::flush(){
225     camera_q_node* node = NULL;
226     struct cam_list *head = NULL;
227     struct cam_list *pos = NULL;
228 
229     pthread_mutex_lock(&m_lock);
230     head = &m_head.list;
231     pos = head->next;
232 
233     while(pos != head) {
234         node = member_of(pos, camera_q_node, list);
235         pos = pos->next;
236         cam_list_del_node(&node->list);
237         m_size--;
238 
239         if (NULL != node->data) {
240             if (m_dataFn) {
241                 m_dataFn(node->data, m_userData);
242             }
243             free(node->data);
244         }
245         free(node);
246 
247     }
248     m_size = 0;
249     pthread_mutex_unlock(&m_lock);
250 }
251 
252 /*===========================================================================
253  * FUNCTION   : flushNodes
254  *
255  * DESCRIPTION: flush only specific nodes, depending on
256  *              the given matching function.
257  *
258  * PARAMETERS :
259  *   @match   : matching function
260  *
261  * RETURN     : None
262  *==========================================================================*/
flushNodes(match_fn match)263 void QCameraQueue::flushNodes(match_fn match){
264     camera_q_node* node = NULL;
265     struct cam_list *head = NULL;
266     struct cam_list *pos = NULL;
267 
268     if ( NULL == match ) {
269         return;
270     }
271 
272     pthread_mutex_lock(&m_lock);
273     head = &m_head.list;
274     pos = head->next;
275 
276     while(pos != head) {
277         node = member_of(pos, camera_q_node, list);
278         pos = pos->next;
279         if ( match(node->data, m_userData) ) {
280             cam_list_del_node(&node->list);
281             m_size--;
282 
283             if (NULL != node->data) {
284                 if (m_dataFn) {
285                     m_dataFn(node->data, m_userData);
286                 }
287                 free(node->data);
288             }
289             free(node);
290         }
291     }
292     pthread_mutex_unlock(&m_lock);
293 }
294 
295 }; // namespace qcamera
296