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   : 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