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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 : dequeue 208 * 209 * DESCRIPTION: dequeue data from the queue 210 * 211 * PARAMETERS : 212 * @bFromHead : if true, dequeue from the head 213 * if false, dequeue from the tail 214 * 215 * RETURN : data ptr. NULL if not any data in the queue. 216 *==========================================================================*/ 217 void* QCameraQueue::dequeue(bool bFromHead) 218 { 219 camera_q_node* node = NULL; 220 void* data = NULL; 221 struct cam_list *head = NULL; 222 struct cam_list *pos = NULL; 223 224 pthread_mutex_lock(&m_lock); 225 if (m_active) { 226 head = &m_head.list; 227 if (bFromHead) { 228 pos = head->next; 229 } else { 230 pos = head->prev; 231 } 232 if (pos != head) { 233 node = member_of(pos, camera_q_node, list); 234 cam_list_del_node(&node->list); 235 m_size--; 236 } 237 } 238 pthread_mutex_unlock(&m_lock); 239 240 if (NULL != node) { 241 data = node->data; 242 free(node); 243 } 244 245 return data; 246 } 247 248 /*=========================================================================== 249 * FUNCTION : flush 250 * 251 * DESCRIPTION: flush all nodes from the queue, queue will be empty after this 252 * operation. 253 * 254 * PARAMETERS : None 255 * 256 * RETURN : None 257 *==========================================================================*/ 258 void QCameraQueue::flush(){ 259 camera_q_node* node = NULL; 260 struct cam_list *head = NULL; 261 struct cam_list *pos = NULL; 262 263 pthread_mutex_lock(&m_lock); 264 if (m_active) { 265 head = &m_head.list; 266 pos = head->next; 267 268 while(pos != head) { 269 node = member_of(pos, camera_q_node, list); 270 pos = pos->next; 271 cam_list_del_node(&node->list); 272 m_size--; 273 274 if (NULL != node->data) { 275 if (m_dataFn) { 276 m_dataFn(node->data, m_userData); 277 } 278 free(node->data); 279 } 280 free(node); 281 282 } 283 m_size = 0; 284 m_active = false; 285 } 286 pthread_mutex_unlock(&m_lock); 287 } 288 289 /*=========================================================================== 290 * FUNCTION : flushNodes 291 * 292 * DESCRIPTION: flush only specific nodes, depending on 293 * the given matching function. 294 * 295 * PARAMETERS : 296 * @match : matching function 297 * 298 * RETURN : None 299 *==========================================================================*/ 300 void QCameraQueue::flushNodes(match_fn match){ 301 camera_q_node* node = NULL; 302 struct cam_list *head = NULL; 303 struct cam_list *pos = NULL; 304 305 if ( NULL == match ) { 306 return; 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 ( match(node->data, m_userData) ) { 318 cam_list_del_node(&node->list); 319 m_size--; 320 321 if (NULL != node->data) { 322 if (m_dataFn) { 323 m_dataFn(node->data, m_userData); 324 } 325 free(node->data); 326 } 327 free(node); 328 } 329 } 330 } 331 pthread_mutex_unlock(&m_lock); 332 } 333 334 /*=========================================================================== 335 * FUNCTION : flushNodes 336 * 337 * DESCRIPTION: flush only specific nodes, depending on 338 * the given matching function. 339 * 340 * PARAMETERS : 341 * @match : matching function 342 * 343 * RETURN : None 344 *==========================================================================*/ 345 void QCameraQueue::flushNodes(match_fn_data match, void *match_data){ 346 camera_q_node* node = NULL; 347 struct cam_list *head = NULL; 348 struct cam_list *pos = NULL; 349 350 if ( NULL == match ) { 351 return; 352 } 353 354 pthread_mutex_lock(&m_lock); 355 if (m_active) { 356 head = &m_head.list; 357 pos = head->next; 358 359 while(pos != head) { 360 node = member_of(pos, camera_q_node, list); 361 pos = pos->next; 362 if ( match(node->data, m_userData, match_data) ) { 363 cam_list_del_node(&node->list); 364 m_size--; 365 366 if (NULL != node->data) { 367 if (m_dataFn) { 368 m_dataFn(node->data, m_userData); 369 } 370 free(node->data); 371 } 372 free(node); 373 } 374 } 375 } 376 pthread_mutex_unlock(&m_lock); 377 } 378 379 }; // namespace qcamera 380