mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
Refine thread.
This commit is contained in:
parent
5bec6a4fdd
commit
44014683e1
2 changed files with 45 additions and 107 deletions
|
@ -61,24 +61,16 @@ namespace internal
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsThread::SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t ims, bool joinable)
|
SrsThread::SrsThread(const char* n, ISrsThreadHandler* h, int64_t ims, bool j)
|
||||||
{
|
{
|
||||||
_name = name;
|
name = n;
|
||||||
handler = thread_handler;
|
handler = h;
|
||||||
cims = ims;
|
cims = ims;
|
||||||
|
|
||||||
tid = NULL;
|
trd = NULL;
|
||||||
loop = false;
|
loop = false;
|
||||||
really_terminated = true;
|
context_id = -1;
|
||||||
_cid = -1;
|
joinable = j;
|
||||||
_joinable = joinable;
|
|
||||||
disposed = false;
|
|
||||||
|
|
||||||
// in start(), the thread cycle method maybe stop and remove the thread itself,
|
|
||||||
// and the thread start() is waiting for the _cid, and segment fault then.
|
|
||||||
// @see https://github.com/ossrs/srs/issues/110
|
|
||||||
// thread will set _cid, callback on_thread_start(), then wait for the can_run signal.
|
|
||||||
can_run = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsThread::~SrsThread()
|
SrsThread::~SrsThread()
|
||||||
|
@ -88,50 +80,50 @@ namespace internal
|
||||||
|
|
||||||
int SrsThread::cid()
|
int SrsThread::cid()
|
||||||
{
|
{
|
||||||
return _cid;
|
return context_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsThread::start()
|
int SrsThread::start()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if(tid) {
|
if(trd) {
|
||||||
srs_info("thread %s already running.", _name);
|
srs_info("thread %s already running.", _name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((tid = st_thread_create(thread_fun, this, (_joinable? 1:0), 0)) == NULL){
|
loop = true;
|
||||||
|
|
||||||
|
if((trd = st_thread_create(pfn, this, (joinable? 1:0), 0)) == NULL){
|
||||||
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
||||||
srs_error("st_thread_create failed. ret=%d", ret);
|
srs_error("st_thread_create failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = false;
|
|
||||||
// we set to loop to true for thread to run.
|
|
||||||
loop = true;
|
|
||||||
|
|
||||||
// wait for cid to ready, for parent thread to get the cid.
|
|
||||||
while (_cid < 0) {
|
|
||||||
st_usleep(10 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, cycle thread can run.
|
|
||||||
can_run = true;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsThread::stop()
|
void SrsThread::stop()
|
||||||
{
|
{
|
||||||
if (!tid) {
|
if (!trd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose();
|
// notify the cycle to stop loop.
|
||||||
|
loop = false;
|
||||||
|
|
||||||
_cid = -1;
|
// the interrupt will cause the socket to read/write error,
|
||||||
can_run = false;
|
// which will terminate the cycle thread.
|
||||||
tid = NULL;
|
st_thread_interrupt(trd);
|
||||||
|
|
||||||
|
// when joinable, wait util quit.
|
||||||
|
if (joinable) {
|
||||||
|
// wait the thread to exit.
|
||||||
|
int ret = st_thread_join(trd, NULL);
|
||||||
|
srs_assert(ret == ERROR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
trd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsThread::can_loop()
|
bool SrsThread::can_loop()
|
||||||
|
@ -144,46 +136,7 @@ namespace internal
|
||||||
loop = false;
|
loop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsThread::dispose()
|
void SrsThread::cycle()
|
||||||
{
|
|
||||||
if (disposed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// notify the cycle to stop loop.
|
|
||||||
loop = false;
|
|
||||||
|
|
||||||
// the interrupt will cause the socket to read/write error,
|
|
||||||
// which will terminate the cycle thread.
|
|
||||||
st_thread_interrupt(tid);
|
|
||||||
|
|
||||||
// when joinable, wait util quit.
|
|
||||||
if (_joinable) {
|
|
||||||
// wait the thread to exit.
|
|
||||||
int ret = st_thread_join(tid, NULL);
|
|
||||||
if (ret) {
|
|
||||||
srs_warn("core: ignore join thread failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait the thread actually terminated.
|
|
||||||
// sometimes the thread join return -1, for example,
|
|
||||||
// when thread use st_recvfrom, the thread join return -1.
|
|
||||||
// so here, we use a variable to ensure the thread stopped.
|
|
||||||
// @remark even the thread not joinable, we must ensure the thread stopped when stop.
|
|
||||||
while (!really_terminated) {
|
|
||||||
st_usleep(10 * 1000);
|
|
||||||
|
|
||||||
if (really_terminated) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
srs_warn("core: wait thread to actually terminated");
|
|
||||||
}
|
|
||||||
|
|
||||||
disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsThread::thread_cycle()
|
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -191,37 +144,29 @@ namespace internal
|
||||||
// because sometimes we need to merge cid, for example,
|
// because sometimes we need to merge cid, for example,
|
||||||
// the publish thread should use the same cid of connection.
|
// the publish thread should use the same cid of connection.
|
||||||
_srs_context->generate_id();
|
_srs_context->generate_id();
|
||||||
srs_info("thread %s cycle start", _name);
|
srs_info("thread %s cycle start", name);
|
||||||
_cid = _srs_context->get_id();
|
context_id = _srs_context->get_id();
|
||||||
|
|
||||||
srs_assert(handler);
|
srs_assert(handler);
|
||||||
handler->on_thread_start();
|
handler->on_thread_start();
|
||||||
|
|
||||||
// thread is running now.
|
|
||||||
really_terminated = false;
|
|
||||||
|
|
||||||
// wait for cid to ready, for parent thread to get the cid.
|
|
||||||
while (!can_run && loop) {
|
|
||||||
st_usleep(10 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (loop) {
|
while (loop) {
|
||||||
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
||||||
srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret);
|
srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", name, ret);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread %s on before cycle success", _name);
|
srs_info("thread %s on before cycle success", _name);
|
||||||
|
|
||||||
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
||||||
if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
|
if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
|
||||||
srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret);
|
srs_warn("thread %s cycle failed, ignored and retry, ret=%d", name, ret);
|
||||||
}
|
}
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread %s cycle success", _name);
|
srs_info("thread %s cycle success", _name);
|
||||||
|
|
||||||
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
||||||
srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret);
|
srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", name, ret);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread %s on end cycle success", _name);
|
srs_info("thread %s on end cycle success", _name);
|
||||||
|
@ -239,20 +184,17 @@ namespace internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// readly terminated now.
|
srs_info("thread %s cycle finished", name);
|
||||||
really_terminated = true;
|
|
||||||
|
|
||||||
srs_info("thread %s cycle finished", _name);
|
|
||||||
// @remark in this callback, user may delete this, so never use this->xxx anymore.
|
// @remark in this callback, user may delete this, so never use this->xxx anymore.
|
||||||
handler->on_thread_stop();
|
handler->on_thread_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* SrsThread::thread_fun(void* arg)
|
void* SrsThread::pfn(void* arg)
|
||||||
{
|
{
|
||||||
SrsThread* obj = (SrsThread*)arg;
|
SrsThread* obj = (SrsThread*)arg;
|
||||||
srs_assert(obj);
|
srs_assert(obj);
|
||||||
|
|
||||||
obj->thread_cycle();
|
obj->cycle();
|
||||||
|
|
||||||
// delete cid for valgrind to detect memory leak.
|
// delete cid for valgrind to detect memory leak.
|
||||||
SrsThreadContext* ctx = dynamic_cast<SrsThreadContext*>(_srs_context);
|
SrsThreadContext* ctx = dynamic_cast<SrsThreadContext*>(_srs_context);
|
||||||
|
|
|
@ -100,14 +100,11 @@ namespace internal
|
||||||
class SrsThread
|
class SrsThread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
st_thread_t tid;
|
st_thread_t trd;
|
||||||
int _cid;
|
int context_id;
|
||||||
bool loop;
|
bool loop;
|
||||||
bool can_run;
|
bool joinable;
|
||||||
bool really_terminated;
|
const char* name;
|
||||||
bool _joinable;
|
|
||||||
const char* _name;
|
|
||||||
bool disposed;
|
|
||||||
private:
|
private:
|
||||||
ISrsThreadHandler* handler;
|
ISrsThreadHandler* handler;
|
||||||
// The cycle interval in ms.
|
// The cycle interval in ms.
|
||||||
|
@ -115,10 +112,10 @@ namespace internal
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* initialize the thread.
|
* initialize the thread.
|
||||||
* @param name, human readable name for st debug.
|
* @param n, human readable name for st debug.
|
||||||
* @param thread_handler, the cycle handler for the thread.
|
* @param h, the cycle handler for the thread.
|
||||||
* @param ims, the sleep interval in ms when cycle finished.
|
* @param ims, the sleep interval in ms when cycle finished.
|
||||||
* @param joinable, if joinable, other thread must stop the thread.
|
* @param j, if joinable, other thread must stop the thread.
|
||||||
* @remark if joinable, thread never quit itself, or memory leak.
|
* @remark if joinable, thread never quit itself, or memory leak.
|
||||||
* @see: https://github.com/ossrs/srs/issues/78
|
* @see: https://github.com/ossrs/srs/issues/78
|
||||||
* @remark about st debug, see st-1.9/README, _st_iterate_threads_flag
|
* @remark about st debug, see st-1.9/README, _st_iterate_threads_flag
|
||||||
|
@ -127,7 +124,7 @@ namespace internal
|
||||||
* TODO: FIXME: maybe all thread must be reap by others threads,
|
* TODO: FIXME: maybe all thread must be reap by others threads,
|
||||||
* @see: https://github.com/ossrs/srs/issues/77
|
* @see: https://github.com/ossrs/srs/issues/77
|
||||||
*/
|
*/
|
||||||
SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t ims, bool joinable);
|
SrsThread(const char* n, ISrsThreadHandler* h, int64_t ims, bool j);
|
||||||
virtual ~SrsThread();
|
virtual ~SrsThread();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -163,9 +160,8 @@ namespace internal
|
||||||
*/
|
*/
|
||||||
virtual void stop_loop();
|
virtual void stop_loop();
|
||||||
private:
|
private:
|
||||||
virtual void dispose();
|
virtual void cycle();
|
||||||
virtual void thread_cycle();
|
static void* pfn(void* arg);
|
||||||
static void* thread_fun(void* arg);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue