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