mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for bug #237, extract a queue recv thread.
This commit is contained in:
parent
22524f390a
commit
31eb9bf1c1
2 changed files with 143 additions and 76 deletions
|
@ -26,20 +26,101 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_protocol_rtmp.hpp>
|
#include <srs_protocol_rtmp.hpp>
|
||||||
#include <srs_protocol_stack.hpp>
|
#include <srs_protocol_stack.hpp>
|
||||||
|
|
||||||
SrsQueueRecvThread::SrsQueueRecvThread(SrsRtmpServer* rtmp_sdk)
|
ISrsMessageHandler::ISrsMessageHandler()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsMessageHandler::~ISrsMessageHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRecvThread::SrsRecvThread(ISrsMessageHandler* msg_handler, SrsRtmpServer* rtmp_sdk)
|
||||||
|
{
|
||||||
|
handler = msg_handler;
|
||||||
rtmp = rtmp_sdk;
|
rtmp = rtmp_sdk;
|
||||||
trd = new SrsThread(this, 0, true);
|
trd = new SrsThread(this, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsQueueRecvThread::~SrsQueueRecvThread()
|
SrsRecvThread::~SrsRecvThread()
|
||||||
{
|
{
|
||||||
// stop recv thread.
|
// stop recv thread.
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
// destroy the thread.
|
// destroy the thread.
|
||||||
srs_freep(trd);
|
srs_freep(trd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRecvThread::start()
|
||||||
|
{
|
||||||
|
return trd->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsRecvThread::stop()
|
||||||
|
{
|
||||||
|
trd->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRecvThread::cycle()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!handler->can_handle()) {
|
||||||
|
st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsMessage* msg = NULL;
|
||||||
|
|
||||||
|
if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
|
||||||
|
if (!srs_is_client_gracefully_close(ret)) {
|
||||||
|
srs_error("recv client control message failed. ret=%d", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we use no timeout to recv, should never got any error.
|
||||||
|
trd->stop_loop();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("play loop recv message. ret=%d", ret);
|
||||||
|
|
||||||
|
handler->handle(msg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsRecvThread::on_thread_start()
|
||||||
|
{
|
||||||
|
// the multiple messages writev improve performance large,
|
||||||
|
// but the timeout recv will cause 33% sys call performance,
|
||||||
|
// to use isolate thread to recv, can improve about 33% performance.
|
||||||
|
// @see https://github.com/winlinvip/simple-rtmp-server/issues/194
|
||||||
|
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
|
||||||
|
rtmp->set_recv_timeout(ST_UTIME_NO_TIMEOUT);
|
||||||
|
|
||||||
|
// disable the protocol auto response,
|
||||||
|
// for the isolate recv thread should never send any messages.
|
||||||
|
rtmp->set_auto_response(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsRecvThread::on_thread_stop()
|
||||||
|
{
|
||||||
|
// enable the protocol auto response,
|
||||||
|
// for the isolate recv thread terminated.
|
||||||
|
rtmp->set_auto_response(true);
|
||||||
|
|
||||||
|
// reset the timeout to pulse mode.
|
||||||
|
rtmp->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsQueueRecvThread::SrsQueueRecvThread(SrsRtmpServer* rtmp_sdk)
|
||||||
|
: SrsRecvThread(this, rtmp_sdk)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsQueueRecvThread::~SrsQueueRecvThread()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
|
||||||
// clear all messages.
|
// clear all messages.
|
||||||
std::vector<SrsMessage*>::iterator it;
|
std::vector<SrsMessage*>::iterator it;
|
||||||
for (it = queue.begin(); it != queue.end(); ++it) {
|
for (it = queue.begin(); it != queue.end(); ++it) {
|
||||||
|
@ -70,71 +151,20 @@ SrsMessage* SrsQueueRecvThread::pump()
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsQueueRecvThread::start()
|
bool SrsQueueRecvThread::can_handle()
|
||||||
{
|
{
|
||||||
return trd->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsQueueRecvThread::stop()
|
|
||||||
{
|
|
||||||
trd->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsQueueRecvThread::cycle()
|
|
||||||
{
|
|
||||||
int ret = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
// we only recv one message and then process it,
|
// we only recv one message and then process it,
|
||||||
// for the message may cause the thread to stop,
|
// for the message may cause the thread to stop,
|
||||||
// when stop, the thread is freed, so the messages
|
// when stop, the thread is freed, so the messages
|
||||||
// are dropped.
|
// are dropped.
|
||||||
if (!queue.empty()) {
|
return empty();
|
||||||
st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
|
}
|
||||||
return ret;
|
|
||||||
}
|
int SrsQueueRecvThread::handle(SrsMessage* msg)
|
||||||
|
{
|
||||||
SrsMessage* msg = NULL;
|
|
||||||
|
|
||||||
if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
|
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
|
||||||
srs_error("recv client control message failed. ret=%d", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we use no timeout to recv, should never got any error.
|
|
||||||
trd->stop_loop();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
srs_verbose("play loop recv message. ret=%d", ret);
|
|
||||||
|
|
||||||
// put into queue, the send thread will get and process it,
|
// put into queue, the send thread will get and process it,
|
||||||
// @see SrsRtmpConn::process_play_control_msg
|
// @see SrsRtmpConn::process_play_control_msg
|
||||||
queue.push_back(msg);
|
queue.push_back(msg);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsQueueRecvThread::on_thread_start()
|
return ERROR_SUCCESS;
|
||||||
{
|
|
||||||
// the multiple messages writev improve performance large,
|
|
||||||
// but the timeout recv will cause 33% sys call performance,
|
|
||||||
// to use isolate thread to recv, can improve about 33% performance.
|
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/194
|
|
||||||
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
|
|
||||||
rtmp->set_recv_timeout(ST_UTIME_NO_TIMEOUT);
|
|
||||||
|
|
||||||
// disable the protocol auto response,
|
|
||||||
// for the isolate recv thread should never send any messages.
|
|
||||||
rtmp->set_auto_response(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsQueueRecvThread::on_thread_stop()
|
|
||||||
{
|
|
||||||
// enable the protocol auto response,
|
|
||||||
// for the isolate recv thread terminated.
|
|
||||||
rtmp->set_auto_response(true);
|
|
||||||
|
|
||||||
// reset the timeout to pulse mode.
|
|
||||||
rtmp->set_recv_timeout(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,39 @@ class SrsRtmpServer;
|
||||||
class SrsMessage;
|
class SrsMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the recv thread used to replace the timeout recv,
|
* for the recv thread to handle the message.
|
||||||
* which hurt performance for the epoll_ctrl is frequently used.
|
*/
|
||||||
* @see: SrsRtmpConn::playing
|
class ISrsMessageHandler
|
||||||
* @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
|
|
||||||
*/
|
|
||||||
class SrsQueueRecvThread : public ISrsThreadHandler
|
|
||||||
{
|
{
|
||||||
private:
|
public:
|
||||||
|
ISrsMessageHandler();
|
||||||
|
virtual ~ISrsMessageHandler();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* whether the handler can handle,
|
||||||
|
* for example, when queue recv handler got an message,
|
||||||
|
* it wait the user to process it, then the recv thread
|
||||||
|
* never recv message util the handler is ok.
|
||||||
|
*/
|
||||||
|
virtual bool can_handle() = 0;
|
||||||
|
/**
|
||||||
|
* process the received message.
|
||||||
|
*/
|
||||||
|
virtual int handle(SrsMessage* msg) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the recv thread, use message handler to handle each received message.
|
||||||
|
*/
|
||||||
|
class SrsRecvThread : public ISrsThreadHandler
|
||||||
|
{
|
||||||
|
protected:
|
||||||
SrsThread* trd;
|
SrsThread* trd;
|
||||||
|
ISrsMessageHandler* handler;
|
||||||
SrsRtmpServer* rtmp;
|
SrsRtmpServer* rtmp;
|
||||||
std::vector<SrsMessage*> queue;
|
|
||||||
public:
|
public:
|
||||||
SrsQueueRecvThread(SrsRtmpServer* rtmp_sdk);
|
SrsRecvThread(ISrsMessageHandler* msg_handler, SrsRtmpServer* rtmp_sdk);
|
||||||
virtual ~SrsQueueRecvThread();
|
virtual ~SrsRecvThread();
|
||||||
public:
|
|
||||||
virtual bool empty();
|
|
||||||
virtual int size();
|
|
||||||
virtual SrsMessage* pump();
|
|
||||||
public:
|
public:
|
||||||
virtual int start();
|
virtual int start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
@ -65,5 +80,27 @@ public:
|
||||||
virtual void on_thread_stop();
|
virtual void on_thread_stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the recv thread used to replace the timeout recv,
|
||||||
|
* which hurt performance for the epoll_ctrl is frequently used.
|
||||||
|
* @see: SrsRtmpConn::playing
|
||||||
|
* @see: https://github.com/winlinvip/simple-rtmp-server/issues/217
|
||||||
|
*/
|
||||||
|
class SrsQueueRecvThread : virtual public ISrsMessageHandler, virtual public SrsRecvThread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<SrsMessage*> queue;
|
||||||
|
public:
|
||||||
|
SrsQueueRecvThread(SrsRtmpServer* rtmp_sdk);
|
||||||
|
virtual ~SrsQueueRecvThread();
|
||||||
|
public:
|
||||||
|
virtual bool empty();
|
||||||
|
virtual int size();
|
||||||
|
virtual SrsMessage* pump();
|
||||||
|
public:
|
||||||
|
virtual bool can_handle();
|
||||||
|
virtual int handle(SrsMessage* msg);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue