/* 
 | 
 * xcam_thread.cpp - Thread 
 | 
 * 
 | 
 *  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> 
 | 
 */ 
 | 
  
 | 
#include "xcam_thread.h" 
 | 
#include "xcam_mutex.h" 
 | 
#include <errno.h> 
 | 
#include <signal.h> 
 | 
  
 | 
namespace XCam { 
 | 
  
 | 
Thread::Thread (const char *name) 
 | 
    : _name (NULL) 
 | 
    , _thread_id (0) 
 | 
    , _started (false) 
 | 
    , _stopped (true) 
 | 
{ 
 | 
    if (name) 
 | 
        _name = strndup (name, XCAM_MAX_STR_SIZE); 
 | 
  
 | 
    XCAM_LOG_DEBUG ("Thread(%s) construction", XCAM_STR(_name)); 
 | 
} 
 | 
  
 | 
Thread::~Thread () 
 | 
{ 
 | 
    XCAM_LOG_DEBUG ("Thread(%s) destruction", XCAM_STR(_name)); 
 | 
  
 | 
    if (_name) 
 | 
        xcam_free (_name); 
 | 
} 
 | 
  
 | 
int 
 | 
Thread::thread_func (void *user_data) 
 | 
{ 
 | 
    Thread *thread = (Thread *)user_data; 
 | 
    bool ret = true; 
 | 
  
 | 
    { 
 | 
        // Make sure running after start 
 | 
        SmartLock locker(thread->_mutex); 
 | 
        pthread_detach (pthread_self()); 
 | 
    } 
 | 
    ret = thread->started (); 
 | 
  
 | 
    sigset_t set; 
 | 
  
 | 
    /* Block SIGQUIT and SIGTERM */ 
 | 
  
 | 
    sigemptyset(&set); 
 | 
    sigaddset(&set, SIGQUIT); 
 | 
    sigaddset(&set, SIGINT); 
 | 
    sigaddset(&set, SIGTERM); 
 | 
    pthread_sigmask(SIG_BLOCK, &set, NULL); 
 | 
    while (true) { 
 | 
        { 
 | 
            SmartLock locker(thread->_mutex); 
 | 
            if (!thread->_started || ret == false) { 
 | 
                thread->_started = false; 
 | 
                thread->_thread_id = 0; 
 | 
                ret = false; 
 | 
                break; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        ret = thread->loop (); 
 | 
    } 
 | 
  
 | 
    thread->stopped (); 
 | 
  
 | 
    { 
 | 
        SmartLock locker(thread->_mutex); 
 | 
        thread->_stopped = true; 
 | 
    } 
 | 
    thread->_exit_cond.broadcast (); 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
bool 
 | 
Thread::started () 
 | 
{ 
 | 
    XCAM_LOG_DEBUG ("Thread(%s) started", XCAM_STR(_name)); 
 | 
    return true; 
 | 
} 
 | 
  
 | 
void 
 | 
Thread::stopped () 
 | 
{ 
 | 
    XCAM_LOG_DEBUG ("Thread(%s) stopped", XCAM_STR(_name)); 
 | 
} 
 | 
  
 | 
bool Thread::start () 
 | 
{ 
 | 
    SmartLock locker(_mutex); 
 | 
    if (_started) 
 | 
        return true; 
 | 
  
 | 
    if (pthread_create (&_thread_id, NULL, (void * (*)(void*))thread_func, this) != 0) 
 | 
        return false; 
 | 
    _started = true; 
 | 
    _stopped = false; 
 | 
  
 | 
#ifdef __USE_GNU 
 | 
    char thread_name[16]; 
 | 
    xcam_mem_clear (thread_name); 
 | 
    snprintf (thread_name, sizeof (thread_name), "xc:%s", XCAM_STR(_name)); 
 | 
    int ret = pthread_setname_np (_thread_id, thread_name); 
 | 
    if (ret != 0) { 
 | 
        XCAM_LOG_WARNING ("Thread(%s) set name to thread_id failed.(%d, %s)", XCAM_STR(_name), ret, strerror(ret)); 
 | 
    } 
 | 
#endif 
 | 
  
 | 
    return true; 
 | 
} 
 | 
  
 | 
bool 
 | 
Thread::emit_stop () 
 | 
{ 
 | 
    SmartLock locker(_mutex); 
 | 
    _started = false; 
 | 
    return true; 
 | 
} 
 | 
  
 | 
bool Thread::stop () 
 | 
{ 
 | 
    XCAM_LOG_DEBUG ("stop thread(%s) _started: %d _stopped: %d", 
 | 
                    XCAM_STR(_name), _started, _stopped); 
 | 
  
 | 
    emit_stop(); 
 | 
  
 | 
    SmartLock locker(_mutex); 
 | 
    while (!_stopped) { 
 | 
        _exit_cond.wait(_mutex); 
 | 
    } 
 | 
    return true; 
 | 
} 
 | 
  
 | 
bool Thread::is_running () 
 | 
{ 
 | 
    SmartLock locker(_mutex); 
 | 
    return _started; 
 | 
} 
 | 
  
 | 
}; 
 |