+tbm_surface_queue_error_e
+tbm_surface_queue_can_dequeue_wait_timeout(tbm_surface_queue_h surface_queue, int ms_timeout)
+{
+ int ret;
+ struct timespec tp;
+
+ _tbm_surf_queue_mutex_lock();
+ _tbm_set_last_result(TBM_ERROR_NONE);
+
+ TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+ TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+ _tbm_surf_queue_mutex_unlock();
+
+ _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
+
+ _tbm_surf_queue_mutex_lock();
+
+ TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+ TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+ pthread_mutex_lock(&surface_queue->lock);
+
+ TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
+
+ if (_queue_is_empty(&surface_queue->free_queue)) {
+ if (surface_queue->impl && surface_queue->impl->need_attach)
+ surface_queue->impl->need_attach(surface_queue);
+ }
+
+ if (!_queue_is_empty(&surface_queue->free_queue)) {
+ pthread_mutex_unlock(&surface_queue->lock);
+ _tbm_surf_queue_mutex_unlock();
+ return TBM_SURFACE_QUEUE_ERROR_NONE;
+ }
+
+ _tbm_surf_queue_mutex_unlock();
+
+ while (1) {
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ if (ms_timeout > 1000)
+ tp.tv_sec += ms_timeout / 1000;
+
+ tp.tv_nsec += (ms_timeout % 1000) * 1000000;
+
+ if (tp.tv_nsec > 1000000000L) {
+ tp.tv_sec++;
+ tp.tv_nsec -= 1000000000L;
+ }
+
+ ret = pthread_cond_timedwait(&surface_queue->free_cond, &surface_queue->lock, &tp);
+ if (ret) {
+ if (ret == ETIMEDOUT) {
+ TBM_ERR("surface_queue:%p can dequeue wait timeout", surface_queue);
+ pthread_mutex_unlock(&surface_queue->lock);
+ return TBM_SURFACE_QUEUE_ERROR_TIMEOUT;
+ } else {
+ TBM_INFO("surface_queue:%p timedwait error retry wait", surface_queue);
+ }
+ } else {
+ pthread_mutex_unlock(&surface_queue->lock);
+ return TBM_SURFACE_QUEUE_ERROR_NONE;
+ }
+ }
+}
+