fix deadlock of cl processor

 * deadlock caused by 3a stats buffer waiting and 3a results apply
 * reduce latency on stats queue wait
diff --git a/xcore/buffer_pool.cpp b/xcore/buffer_pool.cpp
index a761af4..5ead0dd 100644
--- a/xcore/buffer_pool.cpp
+++ b/xcore/buffer_pool.cpp
@@ -174,7 +174,7 @@
         SmartLock lock (_mutex);
         _started = false;
     }
-    _buf_list.wakeup ();
+    _buf_list.pause_pop ();
 }
 
 void
diff --git a/xcore/image_processor.cpp b/xcore/image_processor.cpp
index 9cba733..fde24b0 100644
--- a/xcore/image_processor.cpp
+++ b/xcore/image_processor.cpp
@@ -87,13 +87,63 @@
     return false;
 }
 
+class X3aResultsProcessThread
+    : public Thread
+{
+    typedef SafeList<X3aResult> ResultQueue;
+public:
+    X3aResultsProcessThread (ImageProcessor *processor)
+        : Thread ("x3a_results_process_thread")
+        , _processor (processor)
+    {}
+    ~X3aResultsProcessThread () {}
+
+    XCamReturn push_result (SmartPtr<X3aResult> &result) {
+        _queue.push (result);
+        return XCAM_RETURN_NO_ERROR;
+    }
+
+    void triger_stop () {
+        _queue.pause_pop ();
+    }
+
+    virtual bool loop ();
+
+private:
+    ImageProcessor  *_processor;
+    ResultQueue      _queue;
+};
+
+bool X3aResultsProcessThread::loop ()
+{
+    X3aResultList result_list;
+    SmartPtr<X3aResult> result;
+
+    result = _queue.pop (-1);
+    if (!result.ptr ())
+        return false;
+
+    result_list.push_back (result);
+    while ((result = _queue.pop (0)).ptr ()) {
+        result_list.push_back (result);
+    }
+
+    XCamReturn ret = _processor->process_3a_results (result_list);
+    if (ret != XCAM_RETURN_NO_ERROR) {
+        XCAM_LOG_DEBUG ("processing 3a result failed");
+    }
+
+    return true;
+}
 ImageProcessor::ImageProcessor (const char* name)
     : _name (NULL)
     , _callback (NULL)
 {
-    _processor_thread = new ImageProcessorThread (this);
     if (name)
         _name = strdup (name);
+
+    _processor_thread = new ImageProcessorThread (this);
+    _results_thread = new X3aResultsProcessThread (this);
 }
 
 ImageProcessor::~ImageProcessor ()
@@ -113,7 +163,10 @@
 XCamReturn
 ImageProcessor::start()
 {
-    if (!_processor_thread->start()) {
+    if (!_results_thread->start ()) {
+        return XCAM_RETURN_ERROR_THREAD;
+    }
+    if (!_processor_thread->start ()) {
         return XCAM_RETURN_ERROR_THREAD;
     }
     XCAM_LOG_INFO ("ImageProcessor(%s) started", XCAM_STR (_name));
@@ -123,11 +176,13 @@
 XCamReturn
 ImageProcessor::stop()
 {
-    _video_buf_queue.wakeup ();
+    _video_buf_queue.pause_pop ();
+    _results_thread->triger_stop ();
 
     emit_stop ();
 
     _processor_thread->stop ();
+    _results_thread->stop ();
     XCAM_LOG_DEBUG ("ImageProcessor(%s) stopped", XCAM_STR (_name));
     return XCAM_RETURN_NO_ERROR;
 }
@@ -145,6 +200,40 @@
 XCamReturn
 ImageProcessor::push_3a_results (X3aResultList &results)
 {
+    XCAM_ASSERT (!results.empty ());
+    XCamReturn ret = XCAM_RETURN_NO_ERROR;
+    for (X3aResultList::iterator i_res = results.begin();
+            i_res != results.end(); ++i_res) {
+        SmartPtr<X3aResult> &res = *i_res;
+
+        ret = _results_thread->push_result (res);
+        if (ret != XCAM_RETURN_NO_ERROR)
+            break;
+    }
+
+    XCAM_FAIL_RETURN(
+        WARNING,
+        ret == XCAM_RETURN_NO_ERROR,
+        ret,
+        "processor(%s) push 3a results failed", XCAM_STR(get_name()));
+    return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
+{
+    XCamReturn ret = _results_thread->push_result (result);
+    XCAM_FAIL_RETURN(
+        WARNING,
+        ret == XCAM_RETURN_NO_ERROR,
+        ret,
+        "processor(%s) push 3a result failed", XCAM_STR(get_name()));
+    return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::process_3a_results (X3aResultList &results)
+{
     X3aResultList valid_results;
     XCamReturn ret = XCAM_RETURN_NO_ERROR;
 
@@ -171,7 +260,7 @@
 }
 
 XCamReturn
-ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
+ImageProcessor::process_3a_result (SmartPtr<X3aResult> &result)
 {
     X3aResultList valid_results;
     XCamReturn ret = XCAM_RETURN_NO_ERROR;
diff --git a/xcore/image_processor.h b/xcore/image_processor.h
index 38f5920..611f6bd 100644
--- a/xcore/image_processor.h
+++ b/xcore/image_processor.h
@@ -45,11 +45,13 @@
 };
 
 class ImageProcessorThread;
+class X3aResultsProcessThread;
 
 /* base class, ImageProcessor */
 class ImageProcessor
 {
     friend class ImageProcessorThread;
+    friend class X3aResultsProcessThread;
 
     typedef SafeList<VideoBuffer> VideoBufQueue;
 
@@ -81,14 +83,18 @@
     void filter_valid_results (X3aResultList &input, X3aResultList &valid_results);
     XCamReturn buffer_process_loop ();
 
+    XCamReturn process_3a_results (X3aResultList &results);
+    XCamReturn process_3a_result (SmartPtr<X3aResult> &result);
+
 private:
     XCAM_DEAD_COPY (ImageProcessor);
 
 protected:
-    char                          *_name;
-    ImageProcessCallback          *_callback;
-    SmartPtr<ImageProcessorThread> _processor_thread;
-    VideoBufQueue                  _video_buf_queue;
+    char                               *_name;
+    ImageProcessCallback               *_callback;
+    SmartPtr<ImageProcessorThread>      _processor_thread;
+    VideoBufQueue                       _video_buf_queue;
+    SmartPtr<X3aResultsProcessThread>   _results_thread;
 };
 
 };
diff --git a/xcore/safe_list.h b/xcore/safe_list.h
index 5c465c9..c321064 100644
--- a/xcore/safe_list.h
+++ b/xcore/safe_list.h
@@ -35,7 +35,9 @@
 public:
     typedef SmartPtr<OBj> ObjPtr;
 
-    SafeList () {}
+    SafeList ()
+        : _pop_paused (false)
+    {}
     ~SafeList () {
     }
 
@@ -56,12 +58,22 @@
     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 ();
 
 private:
     std::list<ObjPtr> _obj_list;
     Mutex             _mutex;
     XCam::Cond        _new_obj_cond;
+    bool              _pop_paused;
 };
 
 
@@ -72,6 +84,9 @@
     SmartLock lock (_mutex);
     int code = 0;
 
+    if (_pop_paused)
+        return NULL;
+
     if (_obj_list.empty()) {
         if (timeout < 0)
             code = _new_obj_cond.wait(_mutex);
diff --git a/xcore/x3a_analyzer.cpp b/xcore/x3a_analyzer.cpp
index c119d44..4e02f35 100644
--- a/xcore/x3a_analyzer.cpp
+++ b/xcore/x3a_analyzer.cpp
@@ -33,7 +33,7 @@
     ~AnalyzerThread ();
 
     void triger_stop() {
-        _3a_stats_queue.wakeup ();
+        _3a_stats_queue.pause_pop ();
     }
     bool push_stats (const SmartPtr<X3aStats> &stats);
 
@@ -46,7 +46,7 @@
 
 private:
     X3aAnalyzer               *_analyzer;
-    SafeList<X3aStats> _3a_stats_queue;
+    SafeList<X3aStats>         _3a_stats_queue;
 };
 
 AnalyzerThread::AnalyzerThread (X3aAnalyzer *analyzer)
@@ -86,11 +86,17 @@
 AnalyzerThread::loop ()
 {
     const static int32_t timeout = -1;
+    SmartPtr<X3aStats> latest_stats;
     SmartPtr<X3aStats> stats = _3a_stats_queue.pop (timeout);
     if (!stats.ptr()) {
         XCAM_LOG_DEBUG ("analyzer thread got empty stats, stop thread");
         return false;
     }
+    //while ((latest_stats = _3a_stats_queue.pop (0)).ptr ()) {
+    //    stats = latest_stats;
+    //    XCAM_LOG_WARNING ("lost 3a stats since 3a analyzer too slow");
+    //}
+
     XCamReturn ret = _analyzer->analyze_3a_statistics (stats);
     if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
         return true;