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
34namespace qcamera {
35
36/*===========================================================================
37 * FUNCTION   : QCameraQueue
38 *
39 * DESCRIPTION: default constructor of QCameraQueue
40 *
41 * PARAMETERS : None
42 *
43 * RETURN     : None
44 *==========================================================================*/
45QCameraQueue::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 *==========================================================================*/
65QCameraQueue::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 *==========================================================================*/
83QCameraQueue::~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 *==========================================================================*/
98bool 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 *==========================================================================*/
119bool 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 *==========================================================================*/
149bool 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 *==========================================================================*/
185void* 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 *==========================================================================*/
224void 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 *==========================================================================*/
263void 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