/* 
 | 
 * safe_list.h - safe list template 
 | 
 * 
 | 
 *  Copyright (c) 2014 Intel Corporation 
 | 
 * 
 | 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 | 
 * you may not use this file except in compliance with the License. 
 | 
 * You may obtain a copy of the License at 
 | 
 * 
 | 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 | 
 * 
 | 
 * Unless required by applicable law or agreed to in writing, software 
 | 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 | 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 | 
 * See the License for the specific language governing permissions and 
 | 
 * limitations under the License. 
 | 
 * 
 | 
 * Author: Wind Yuan <feng.yuan@intel.com> 
 | 
 */ 
 | 
  
 | 
#ifndef XCAM_SAFE_LIST_H 
 | 
#define XCAM_SAFE_LIST_H 
 | 
  
 | 
#include <base/xcam_defs.h> 
 | 
#include <base/xcam_common.h> 
 | 
#include <errno.h> 
 | 
#include <list> 
 | 
#include <xcam_mutex.h> 
 | 
  
 | 
namespace XCam { 
 | 
  
 | 
template<class OBj> 
 | 
class SafeList { 
 | 
public: 
 | 
    typedef SmartPtr<OBj> ObjPtr; 
 | 
    typedef std::list<ObjPtr> ObjList; 
 | 
    typedef typename std::list<typename SafeList<OBj>::ObjPtr>::iterator ObjIter; 
 | 
  
 | 
    SafeList () 
 | 
        : _pop_paused (false) 
 | 
    {} 
 | 
    ~SafeList () { 
 | 
    } 
 | 
  
 | 
    /* 
 | 
     * timeout, -1,  wait until wakeup 
 | 
     *         >=0,  wait for @timeout microsseconds 
 | 
    */ 
 | 
    inline ObjPtr pop (int32_t timeout = -1); 
 | 
    inline bool push (const ObjPtr &obj); 
 | 
    inline bool erase (const ObjPtr &obj); 
 | 
    inline ObjPtr front (); 
 | 
    uint32_t size () { 
 | 
        SmartLock lock(_mutex); 
 | 
        return _obj_list.size(); 
 | 
    } 
 | 
    bool is_empty () { 
 | 
        SmartLock lock(_mutex); 
 | 
        return _obj_list.empty(); 
 | 
    } 
 | 
    void wakeup () { 
 | 
        _new_obj_cond.broadcast (); 
 | 
    } 
 | 
    void pause_pop () { 
 | 
        SmartLock lock(_mutex); 
 | 
        _pop_paused = true; 
 | 
        wakeup (); 
 | 
    } 
 | 
    void resume_pop () { 
 | 
        SmartLock lock(_mutex); 
 | 
        _pop_paused = false; 
 | 
    } 
 | 
    inline void clear (); 
 | 
  
 | 
protected: 
 | 
    ObjList           _obj_list; 
 | 
    Mutex             _mutex; 
 | 
    XCam::Cond        _new_obj_cond; 
 | 
    volatile bool              _pop_paused; 
 | 
}; 
 | 
  
 | 
  
 | 
template<class OBj> 
 | 
typename SafeList<OBj>::ObjPtr 
 | 
SafeList<OBj>::pop (int32_t timeout) 
 | 
{ 
 | 
    SmartLock lock (_mutex); 
 | 
    int code = 0; 
 | 
  
 | 
    while (!_pop_paused && _obj_list.empty() && code == 0) { 
 | 
        if (timeout < 0) 
 | 
            code = _new_obj_cond.wait(_mutex); 
 | 
        else 
 | 
            code = _new_obj_cond.timedwait(_mutex, timeout); 
 | 
    } 
 | 
  
 | 
    if (_pop_paused) 
 | 
        return NULL; 
 | 
  
 | 
    if (_obj_list.empty()) { 
 | 
        if (code == ETIMEDOUT) { 
 | 
            XCAM_LOG_DEBUG ("safe list pop timeout"); 
 | 
        } else { 
 | 
            XCAM_LOG_ERROR ("safe list pop failed, code:%d", code); 
 | 
        } 
 | 
        return NULL; 
 | 
    } 
 | 
  
 | 
    SafeList<OBj>::ObjPtr obj = *_obj_list.begin (); 
 | 
    _obj_list.erase (_obj_list.begin ()); 
 | 
    return obj; 
 | 
} 
 | 
  
 | 
template<class OBj> 
 | 
bool 
 | 
SafeList<OBj>::push (const SafeList<OBj>::ObjPtr &obj) 
 | 
{ 
 | 
    SmartLock lock (_mutex); 
 | 
    _obj_list.push_back (obj); 
 | 
    _new_obj_cond.signal (); 
 | 
    return true; 
 | 
} 
 | 
  
 | 
template<class OBj> 
 | 
bool 
 | 
SafeList<OBj>::erase (const SafeList<OBj>::ObjPtr &obj) 
 | 
{ 
 | 
    XCAM_ASSERT (obj.ptr ()); 
 | 
    SmartLock lock (_mutex); 
 | 
    for (SafeList<OBj>::ObjIter i_obj = _obj_list.begin (); 
 | 
            i_obj != _obj_list.end (); ++i_obj) { 
 | 
        if ((*i_obj).ptr () == obj.ptr ()) { 
 | 
            _obj_list.erase (i_obj); 
 | 
            return true; 
 | 
        } 
 | 
    } 
 | 
    return false; 
 | 
} 
 | 
  
 | 
template<class OBj> 
 | 
typename SafeList<OBj>::ObjPtr 
 | 
SafeList<OBj>::front () 
 | 
{ 
 | 
    SmartLock lock (_mutex); 
 | 
    SafeList<OBj>::ObjIter i = _obj_list.begin (); 
 | 
    if (i == _obj_list.end ()) 
 | 
        return NULL; 
 | 
    return *i; 
 | 
} 
 | 
  
 | 
template<class OBj> 
 | 
void SafeList<OBj>::clear () 
 | 
{ 
 | 
    SmartLock lock (_mutex); 
 | 
    SafeList<OBj>::ObjIter i_obj = _obj_list.begin (); 
 | 
    while (i_obj != _obj_list.end ()) { 
 | 
        _obj_list.erase (i_obj++); 
 | 
    } 
 | 
} 
 | 
  
 | 
}; 
 | 
#endif //XCAM_SAFE_LIST_H 
 |