winlin

move the srs thread to st.

@@ -26,6 +26,230 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -26,6 +26,230 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <srs_kernel_error.hpp> 26 #include <srs_kernel_error.hpp>
27 #include <srs_kernel_log.hpp> 27 #include <srs_kernel_log.hpp>
28 28
  29 +namespace internal
  30 +{
  31 + ISrsThreadHandler::ISrsThreadHandler()
  32 + {
  33 + }
  34 +
  35 + ISrsThreadHandler::~ISrsThreadHandler()
  36 + {
  37 + }
  38 +
  39 + void ISrsThreadHandler::on_thread_start()
  40 + {
  41 + }
  42 +
  43 + int ISrsThreadHandler::on_before_cycle()
  44 + {
  45 + int ret = ERROR_SUCCESS;
  46 + return ret;
  47 + }
  48 +
  49 + int ISrsThreadHandler::on_end_cycle()
  50 + {
  51 + int ret = ERROR_SUCCESS;
  52 + return ret;
  53 + }
  54 +
  55 + void ISrsThreadHandler::on_thread_stop()
  56 + {
  57 + }
  58 +
  59 + SrsThread::SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t interval_us, bool joinable)
  60 + {
  61 + _name = name;
  62 + handler = thread_handler;
  63 + cycle_interval_us = interval_us;
  64 +
  65 + tid = NULL;
  66 + loop = false;
  67 + really_terminated = true;
  68 + _cid = -1;
  69 + _joinable = joinable;
  70 + disposed = false;
  71 +
  72 + // in start(), the thread cycle method maybe stop and remove the thread itself,
  73 + // and the thread start() is waiting for the _cid, and segment fault then.
  74 + // @see https://github.com/simple-rtmp-server/srs/issues/110
  75 + // thread will set _cid, callback on_thread_start(), then wait for the can_run signal.
  76 + can_run = false;
  77 + }
  78 +
  79 + SrsThread::~SrsThread()
  80 + {
  81 + stop();
  82 + }
  83 +
  84 + int SrsThread::cid()
  85 + {
  86 + return _cid;
  87 + }
  88 +
  89 + int SrsThread::start()
  90 + {
  91 + int ret = ERROR_SUCCESS;
  92 +
  93 + if(tid) {
  94 + srs_info("thread %s already running.", _name);
  95 + return ret;
  96 + }
  97 +
  98 + if((tid = st_thread_create(thread_fun, this, (_joinable? 1:0), 0)) == NULL){
  99 + ret = ERROR_ST_CREATE_CYCLE_THREAD;
  100 + srs_error("st_thread_create failed. ret=%d", ret);
  101 + return ret;
  102 + }
  103 +
  104 + // we set to loop to true for thread to run.
  105 + loop = true;
  106 +
  107 + // wait for cid to ready, for parent thread to get the cid.
  108 + while (_cid < 0 && loop) {
  109 + st_usleep(10 * 1000);
  110 + }
  111 +
  112 + // now, cycle thread can run.
  113 + can_run = true;
  114 +
  115 + return ret;
  116 + }
  117 +
  118 + void SrsThread::stop()
  119 + {
  120 + if (!tid) {
  121 + return;
  122 + }
  123 +
  124 + loop = false;
  125 +
  126 + dispose();
  127 +
  128 + tid = NULL;
  129 + }
  130 +
  131 + bool SrsThread::can_loop()
  132 + {
  133 + return loop;
  134 + }
  135 +
  136 + void SrsThread::stop_loop()
  137 + {
  138 + loop = false;
  139 + }
  140 +
  141 + void SrsThread::dispose()
  142 + {
  143 + if (disposed) {
  144 + return;
  145 + }
  146 +
  147 + // the interrupt will cause the socket to read/write error,
  148 + // which will terminate the cycle thread.
  149 + st_thread_interrupt(tid);
  150 +
  151 + // when joinable, wait util quit.
  152 + if (_joinable) {
  153 + // wait the thread to exit.
  154 + int ret = st_thread_join(tid, NULL);
  155 + if (ret) {
  156 + srs_warn("core: ignore join thread failed.");
  157 + }
  158 + }
  159 +
  160 + // wait the thread actually terminated.
  161 + // sometimes the thread join return -1, for example,
  162 + // when thread use st_recvfrom, the thread join return -1.
  163 + // so here, we use a variable to ensure the thread stopped.
  164 + // @remark even the thread not joinable, we must ensure the thread stopped when stop.
  165 + while (!really_terminated) {
  166 + st_usleep(10 * 1000);
  167 +
  168 + if (really_terminated) {
  169 + break;
  170 + }
  171 + srs_warn("core: wait thread to actually terminated");
  172 + }
  173 +
  174 + disposed = true;
  175 + }
  176 +
  177 + void SrsThread::thread_cycle()
  178 + {
  179 + int ret = ERROR_SUCCESS;
  180 +
  181 + _srs_context->generate_id();
  182 + srs_info("thread %s cycle start", _name);
  183 +
  184 + _cid = _srs_context->get_id();
  185 +
  186 + srs_assert(handler);
  187 + handler->on_thread_start();
  188 +
  189 + // thread is running now.
  190 + really_terminated = false;
  191 +
  192 + // wait for cid to ready, for parent thread to get the cid.
  193 + while (!can_run && loop) {
  194 + st_usleep(10 * 1000);
  195 + }
  196 +
  197 + while (loop) {
  198 + if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
  199 + srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret);
  200 + goto failed;
  201 + }
  202 + srs_info("thread %s on before cycle success");
  203 +
  204 + if ((ret = handler->cycle()) != ERROR_SUCCESS) {
  205 + if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
  206 + srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret);
  207 + }
  208 + goto failed;
  209 + }
  210 + srs_info("thread %s cycle success", _name);
  211 +
  212 + if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
  213 + srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret);
  214 + goto failed;
  215 + }
  216 + srs_info("thread %s on end cycle success", _name);
  217 +
  218 + failed:
  219 + if (!loop) {
  220 + break;
  221 + }
  222 +
  223 + // to improve performance, donot sleep when interval is zero.
  224 + // @see: https://github.com/simple-rtmp-server/srs/issues/237
  225 + if (cycle_interval_us != 0) {
  226 + st_usleep(cycle_interval_us);
  227 + }
  228 + }
  229 +
  230 + // readly terminated now.
  231 + really_terminated = true;
  232 +
  233 + handler->on_thread_stop();
  234 + srs_info("thread %s cycle finished", _name);
  235 +
  236 + // when thread terminated normally, also disposed.
  237 + disposed = true;
  238 + }
  239 +
  240 + void* SrsThread::thread_fun(void* arg)
  241 + {
  242 + SrsThread* obj = (SrsThread*)arg;
  243 + srs_assert(obj);
  244 +
  245 + obj->thread_cycle();
  246 +
  247 + st_thread_exit(NULL);
  248 +
  249 + return NULL;
  250 + }
  251 +}
  252 +
29 SrsStSocket::SrsStSocket(st_netfd_t client_stfd) 253 SrsStSocket::SrsStSocket(st_netfd_t client_stfd)
30 { 254 {
31 stfd = client_stfd; 255 stfd = client_stfd;
@@ -35,6 +35,137 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -35,6 +35,137 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 #include <srs_app_st.hpp> 35 #include <srs_app_st.hpp>
36 #include <srs_rtmp_io.hpp> 36 #include <srs_rtmp_io.hpp>
37 37
  38 +// the internal classes, user should never use it.
  39 +// user should use the public classes at the bellow:
  40 +// @see SrsEndlessThread, SrsOneCycleThread, SrsReusableThread
  41 +namespace internal
  42 +{
  43 + /**
  44 + * the handler for the thread, callback interface.
  45 + * the thread model defines as:
  46 + * handler->on_thread_start()
  47 + * while loop:
  48 + * handler->on_before_cycle()
  49 + * handler->cycle()
  50 + * handler->on_end_cycle()
  51 + * if !loop then break for user stop thread.
  52 + * sleep(CycleIntervalMilliseconds)
  53 + * handler->on_thread_stop()
  54 + * when stop, the thread will interrupt the st_thread,
  55 + * which will cause the socket to return error and
  56 + * terminate the cycle thread.
  57 + *
  58 + * @remark why should check can_loop() in cycle method?
  59 + * when thread interrupt, the socket maybe not got EINT,
  60 + * espectially on st_usleep(), so the cycle must check the loop,
  61 + * when handler->cycle() has loop itself, for example:
  62 + * while (true):
  63 + * if (read_from_socket(skt) < 0) break;
  64 + * if thread stop when read_from_socket, it's ok, the loop will break,
  65 + * but when thread stop interrupt the s_usleep(0), then the loop is
  66 + * death loop.
  67 + * in a word, the handler->cycle() must:
  68 + * while (pthread->can_loop()):
  69 + * if (read_from_socket(skt) < 0) break;
  70 + * check the loop, then it works.
  71 + *
  72 + * @remark why should use stop_loop() to terminate thread in itself?
  73 + * in the thread itself, that is the cycle method,
  74 + * if itself want to terminate the thread, should never use stop(),
  75 + * but use stop_loop() to set the loop to false and terminate normally.
  76 + *
  77 + * @remark when should set the interval_us, and when not?
  78 + * the cycle will invoke util cannot loop, eventhough the return code of cycle is error,
  79 + * so the interval_us used to sleep for each cycle.
  80 + */
  81 + class ISrsThreadHandler
  82 + {
  83 + public:
  84 + ISrsThreadHandler();
  85 + virtual ~ISrsThreadHandler();
  86 + public:
  87 + virtual void on_thread_start();
  88 + virtual int on_before_cycle();
  89 + virtual int cycle() = 0;
  90 + virtual int on_end_cycle();
  91 + virtual void on_thread_stop();
  92 + };
  93 +
  94 + /**
  95 + * provides servies from st_thread_t,
  96 + * for common thread usage.
  97 + */
  98 + class SrsThread
  99 + {
  100 + private:
  101 + st_thread_t tid;
  102 + int _cid;
  103 + bool loop;
  104 + bool can_run;
  105 + bool really_terminated;
  106 + bool _joinable;
  107 + const char* _name;
  108 + bool disposed;
  109 + private:
  110 + ISrsThreadHandler* handler;
  111 + int64_t cycle_interval_us;
  112 + public:
  113 + /**
  114 + * initialize the thread.
  115 + * @param name, human readable name for st debug.
  116 + * @param thread_handler, the cycle handler for the thread.
  117 + * @param interval_us, the sleep interval when cycle finished.
  118 + * @param joinable, if joinable, other thread must stop the thread.
  119 + * @remark if joinable, thread never quit itself, or memory leak.
  120 + * @see: https://github.com/simple-rtmp-server/srs/issues/78
  121 + * @remark about st debug, see st-1.9/README, _st_iterate_threads_flag
  122 + */
  123 + /**
  124 + * TODO: FIXME: maybe all thread must be reap by others threads,
  125 + * @see: https://github.com/simple-rtmp-server/srs/issues/77
  126 + */
  127 + SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t interval_us, bool joinable);
  128 + virtual ~SrsThread();
  129 + public:
  130 + /**
  131 + * get the context id. @see: ISrsThreadContext.get_id().
  132 + * used for parent thread to get the id.
  133 + * @remark when start thread, parent thread will block and wait for this id ready.
  134 + */
  135 + virtual int cid();
  136 + /**
  137 + * start the thread, invoke the cycle of handler util
  138 + * user stop the thread.
  139 + * @remark ignore any error of cycle of handler.
  140 + * @remark user can start multiple times, ignore if already started.
  141 + * @remark wait for the cid is set by thread pfn.
  142 + */
  143 + virtual int start();
  144 + /**
  145 + * stop the thread, wait for the thread to terminate.
  146 + * @remark user can stop multiple times, ignore if already stopped.
  147 + */
  148 + virtual void stop();
  149 + public:
  150 + /**
  151 + * whether the thread should loop,
  152 + * used for handler->cycle() which has a loop method,
  153 + * to check this method, break if false.
  154 + */
  155 + virtual bool can_loop();
  156 + /**
  157 + * for the loop thread to stop the loop.
  158 + * other thread can directly use stop() to stop loop and wait for quit.
  159 + * this stop loop method only set loop to false.
  160 + */
  161 + virtual void stop_loop();
  162 + private:
  163 + virtual void dispose();
  164 + virtual void thread_cycle();
  165 + static void* thread_fun(void* arg);
  166 + };
  167 +}
  168 +
38 /** 169 /**
39 * the socket provides TCP socket over st, 170 * the socket provides TCP socket over st,
40 * that is, the sync socket mechanism. 171 * that is, the sync socket mechanism.
@@ -26,229 +26,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -26,229 +26,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <srs_kernel_error.hpp> 26 #include <srs_kernel_error.hpp>
27 #include <srs_kernel_log.hpp> 27 #include <srs_kernel_log.hpp>
28 28
29 -namespace internal {  
30 - ISrsThreadHandler::ISrsThreadHandler()  
31 - {  
32 - }  
33 -  
34 - ISrsThreadHandler::~ISrsThreadHandler()  
35 - {  
36 - }  
37 -  
38 - void ISrsThreadHandler::on_thread_start()  
39 - {  
40 - }  
41 -  
42 - int ISrsThreadHandler::on_before_cycle()  
43 - {  
44 - int ret = ERROR_SUCCESS;  
45 - return ret;  
46 - }  
47 -  
48 - int ISrsThreadHandler::on_end_cycle()  
49 - {  
50 - int ret = ERROR_SUCCESS;  
51 - return ret;  
52 - }  
53 -  
54 - void ISrsThreadHandler::on_thread_stop()  
55 - {  
56 - }  
57 -  
58 - SrsThread::SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t interval_us, bool joinable)  
59 - {  
60 - _name = name;  
61 - handler = thread_handler;  
62 - cycle_interval_us = interval_us;  
63 -  
64 - tid = NULL;  
65 - loop = false;  
66 - really_terminated = true;  
67 - _cid = -1;  
68 - _joinable = joinable;  
69 - disposed = false;  
70 -  
71 - // in start(), the thread cycle method maybe stop and remove the thread itself,  
72 - // and the thread start() is waiting for the _cid, and segment fault then.  
73 - // @see https://github.com/simple-rtmp-server/srs/issues/110  
74 - // thread will set _cid, callback on_thread_start(), then wait for the can_run signal.  
75 - can_run = false;  
76 - }  
77 -  
78 - SrsThread::~SrsThread()  
79 - {  
80 - stop();  
81 - }  
82 -  
83 - int SrsThread::cid()  
84 - {  
85 - return _cid;  
86 - }  
87 -  
88 - int SrsThread::start()  
89 - {  
90 - int ret = ERROR_SUCCESS;  
91 -  
92 - if(tid) {  
93 - srs_info("thread %s already running.", _name);  
94 - return ret;  
95 - }  
96 -  
97 - if((tid = st_thread_create(thread_fun, this, (_joinable? 1:0), 0)) == NULL){  
98 - ret = ERROR_ST_CREATE_CYCLE_THREAD;  
99 - srs_error("st_thread_create failed. ret=%d", ret);  
100 - return ret;  
101 - }  
102 -  
103 - // we set to loop to true for thread to run.  
104 - loop = true;  
105 -  
106 - // wait for cid to ready, for parent thread to get the cid.  
107 - while (_cid < 0 && loop) {  
108 - st_usleep(10 * 1000);  
109 - }  
110 -  
111 - // now, cycle thread can run.  
112 - can_run = true;  
113 -  
114 - return ret;  
115 - }  
116 -  
117 - void SrsThread::stop()  
118 - {  
119 - if (!tid) {  
120 - return;  
121 - }  
122 -  
123 - loop = false;  
124 -  
125 - dispose();  
126 -  
127 - tid = NULL;  
128 - }  
129 -  
130 - bool SrsThread::can_loop()  
131 - {  
132 - return loop;  
133 - }  
134 -  
135 - void SrsThread::stop_loop()  
136 - {  
137 - loop = false;  
138 - }  
139 -  
140 - void SrsThread::dispose()  
141 - {  
142 - if (disposed) {  
143 - return;  
144 - }  
145 -  
146 - // the interrupt will cause the socket to read/write error,  
147 - // which will terminate the cycle thread.  
148 - st_thread_interrupt(tid);  
149 -  
150 - // when joinable, wait util quit.  
151 - if (_joinable) {  
152 - // wait the thread to exit.  
153 - int ret = st_thread_join(tid, NULL);  
154 - if (ret) {  
155 - srs_warn("core: ignore join thread failed.");  
156 - }  
157 - }  
158 -  
159 - // wait the thread actually terminated.  
160 - // sometimes the thread join return -1, for example,  
161 - // when thread use st_recvfrom, the thread join return -1.  
162 - // so here, we use a variable to ensure the thread stopped.  
163 - // @remark even the thread not joinable, we must ensure the thread stopped when stop.  
164 - while (!really_terminated) {  
165 - st_usleep(10 * 1000);  
166 -  
167 - if (really_terminated) {  
168 - break;  
169 - }  
170 - srs_warn("core: wait thread to actually terminated");  
171 - }  
172 -  
173 - disposed = true;  
174 - }  
175 -  
176 - void SrsThread::thread_cycle()  
177 - {  
178 - int ret = ERROR_SUCCESS;  
179 -  
180 - _srs_context->generate_id();  
181 - srs_info("thread %s cycle start", _name);  
182 -  
183 - _cid = _srs_context->get_id();  
184 -  
185 - srs_assert(handler);  
186 - handler->on_thread_start();  
187 -  
188 - // thread is running now.  
189 - really_terminated = false;  
190 -  
191 - // wait for cid to ready, for parent thread to get the cid.  
192 - while (!can_run && loop) {  
193 - st_usleep(10 * 1000);  
194 - }  
195 -  
196 - while (loop) {  
197 - if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {  
198 - srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret);  
199 - goto failed;  
200 - }  
201 - srs_info("thread %s on before cycle success");  
202 -  
203 - if ((ret = handler->cycle()) != ERROR_SUCCESS) {  
204 - if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {  
205 - srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret);  
206 - }  
207 - goto failed;  
208 - }  
209 - srs_info("thread %s cycle success", _name);  
210 -  
211 - if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {  
212 - srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret);  
213 - goto failed;  
214 - }  
215 - srs_info("thread %s on end cycle success", _name);  
216 -  
217 - failed:  
218 - if (!loop) {  
219 - break;  
220 - }  
221 -  
222 - // to improve performance, donot sleep when interval is zero.  
223 - // @see: https://github.com/simple-rtmp-server/srs/issues/237  
224 - if (cycle_interval_us != 0) {  
225 - st_usleep(cycle_interval_us);  
226 - }  
227 - }  
228 -  
229 - // readly terminated now.  
230 - really_terminated = true;  
231 -  
232 - handler->on_thread_stop();  
233 - srs_info("thread %s cycle finished", _name);  
234 -  
235 - // when thread terminated normally, also disposed.  
236 - disposed = true;  
237 - }  
238 -  
239 - void* SrsThread::thread_fun(void* arg)  
240 - {  
241 - SrsThread* obj = (SrsThread*)arg;  
242 - srs_assert(obj);  
243 -  
244 - obj->thread_cycle();  
245 -  
246 - st_thread_exit(NULL);  
247 -  
248 - return NULL;  
249 - }  
250 -}  
251 -  
252 ISrsEndlessThreadHandler::ISrsEndlessThreadHandler() 29 ISrsEndlessThreadHandler::ISrsEndlessThreadHandler()
253 { 30 {
254 } 31 }
@@ -31,136 +31,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,136 +31,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 31
32 #include <srs_app_st.hpp> 32 #include <srs_app_st.hpp>
33 33
34 -// the internal classes, user should never use it.  
35 -// user should use the public classes at the bellow:  
36 -// @see SrsEndlessThread, SrsOneCycleThread, SrsReusableThread  
37 -namespace internal {  
38 - /**  
39 - * the handler for the thread, callback interface.  
40 - * the thread model defines as:  
41 - * handler->on_thread_start()  
42 - * while loop:  
43 - * handler->on_before_cycle()  
44 - * handler->cycle()  
45 - * handler->on_end_cycle()  
46 - * if !loop then break for user stop thread.  
47 - * sleep(CycleIntervalMilliseconds)  
48 - * handler->on_thread_stop()  
49 - * when stop, the thread will interrupt the st_thread,  
50 - * which will cause the socket to return error and  
51 - * terminate the cycle thread.  
52 - *  
53 - * @remark why should check can_loop() in cycle method?  
54 - * when thread interrupt, the socket maybe not got EINT,  
55 - * espectially on st_usleep(), so the cycle must check the loop,  
56 - * when handler->cycle() has loop itself, for example:  
57 - * while (true):  
58 - * if (read_from_socket(skt) < 0) break;  
59 - * if thread stop when read_from_socket, it's ok, the loop will break,  
60 - * but when thread stop interrupt the s_usleep(0), then the loop is  
61 - * death loop.  
62 - * in a word, the handler->cycle() must:  
63 - * while (pthread->can_loop()):  
64 - * if (read_from_socket(skt) < 0) break;  
65 - * check the loop, then it works.  
66 - *  
67 - * @remark why should use stop_loop() to terminate thread in itself?  
68 - * in the thread itself, that is the cycle method,  
69 - * if itself want to terminate the thread, should never use stop(),  
70 - * but use stop_loop() to set the loop to false and terminate normally.  
71 - *  
72 - * @remark when should set the interval_us, and when not?  
73 - * the cycle will invoke util cannot loop, eventhough the return code of cycle is error,  
74 - * so the interval_us used to sleep for each cycle.  
75 - */  
76 - class ISrsThreadHandler  
77 - {  
78 - public:  
79 - ISrsThreadHandler();  
80 - virtual ~ISrsThreadHandler();  
81 - public:  
82 - virtual void on_thread_start();  
83 - virtual int on_before_cycle();  
84 - virtual int cycle() = 0;  
85 - virtual int on_end_cycle();  
86 - virtual void on_thread_stop();  
87 - };  
88 -  
89 - /**  
90 - * provides servies from st_thread_t,  
91 - * for common thread usage.  
92 - */  
93 - class SrsThread  
94 - {  
95 - private:  
96 - st_thread_t tid;  
97 - int _cid;  
98 - bool loop;  
99 - bool can_run;  
100 - bool really_terminated;  
101 - bool _joinable;  
102 - const char* _name;  
103 - bool disposed;  
104 - private:  
105 - ISrsThreadHandler* handler;  
106 - int64_t cycle_interval_us;  
107 - public:  
108 - /**  
109 - * initialize the thread.  
110 - * @param name, human readable name for st debug.  
111 - * @param thread_handler, the cycle handler for the thread.  
112 - * @param interval_us, the sleep interval when cycle finished.  
113 - * @param joinable, if joinable, other thread must stop the thread.  
114 - * @remark if joinable, thread never quit itself, or memory leak.  
115 - * @see: https://github.com/simple-rtmp-server/srs/issues/78  
116 - * @remark about st debug, see st-1.9/README, _st_iterate_threads_flag  
117 - */  
118 - /**  
119 - * TODO: FIXME: maybe all thread must be reap by others threads,  
120 - * @see: https://github.com/simple-rtmp-server/srs/issues/77  
121 - */  
122 - SrsThread(const char* name, ISrsThreadHandler* thread_handler, int64_t interval_us, bool joinable);  
123 - virtual ~SrsThread();  
124 - public:  
125 - /**  
126 - * get the context id. @see: ISrsThreadContext.get_id().  
127 - * used for parent thread to get the id.  
128 - * @remark when start thread, parent thread will block and wait for this id ready.  
129 - */  
130 - virtual int cid();  
131 - /**  
132 - * start the thread, invoke the cycle of handler util  
133 - * user stop the thread.  
134 - * @remark ignore any error of cycle of handler.  
135 - * @remark user can start multiple times, ignore if already started.  
136 - * @remark wait for the cid is set by thread pfn.  
137 - */  
138 - virtual int start();  
139 - /**  
140 - * stop the thread, wait for the thread to terminate.  
141 - * @remark user can stop multiple times, ignore if already stopped.  
142 - */  
143 - virtual void stop();  
144 - public:  
145 - /**  
146 - * whether the thread should loop,  
147 - * used for handler->cycle() which has a loop method,  
148 - * to check this method, break if false.  
149 - */  
150 - virtual bool can_loop();  
151 - /**  
152 - * for the loop thread to stop the loop.  
153 - * other thread can directly use stop() to stop loop and wait for quit.  
154 - * this stop loop method only set loop to false.  
155 - */  
156 - virtual void stop_loop();  
157 - private:  
158 - virtual void dispose();  
159 - virtual void thread_cycle();  
160 - static void* thread_fun(void* arg);  
161 - };  
162 -}  
163 -  
164 /** 34 /**
165 * the endless thread is a loop thread never quit. 35 * the endless thread is a loop thread never quit.
166 * user can create thread always running util server terminate. 36 * user can create thread always running util server terminate.