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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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 *==========================================================================*/ 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