Home | History | Annotate | Download | only in util
      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