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