1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

UniquePtr: Support SrsUniquePtr to replace SrsAutoFree. v6.0.136 (#4109)

To manage an object:

```cpp
// Before
MyClass* ptr = new MyClass();
SrsAutoFree(MyClass, ptr);
ptr->do_something();

// Now
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
```

To manage an array of objects:

```cpp
// Before
char* ptr = new char[10];
SrsAutoFreeA(char, ptr);
ptr[0] = 0xf;

// Now
SrsUniquePtr<char[]> ptr(new char[10]);
ptr[0] = 0xf;
```

In fact, SrsUniquePtr is a limited subset of SrsAutoFree, mainly
managing pointers and arrays. SrsUniquePtr is better than SrsAutoFree
because it has the same API to standard unique ptr.

```cpp
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
MyClass* p = ptr.get();
```

SrsAutoFree actually uses a pointer to a pointer, so it can be set to
NULL, allowing the pointer's value to be changed later (this usage is
different from SrsUniquePtr).

```cpp
// OK to free ptr correctly.
MyClass* ptr;
SrsAutoFree(MyClass, ptr);
ptr = new MyClass();

// Crash because ptr is an invalid pointer.
MyClass* ptr;
SrsUniquePtr<MyClass> ptr(ptr);
ptr = new MyClass();
```

Additionally, SrsAutoFreeH can use specific release functions, which
SrsUniquePtr does not support.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-07-09 10:29:36 +08:00 committed by GitHub
parent baf22d01c1
commit 23d2602c34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 1720 additions and 1669 deletions

View file

@ -129,18 +129,18 @@ srs_error_t SrsBufferCache::cycle()
// the stream cache will create consumer to cache stream,
// which will trigger to fetch stream from origin for edge.
SrsLiveConsumer* consumer = NULL;
SrsAutoFree(SrsLiveConsumer, consumer);
if ((err = live_source->create_consumer(consumer)) != srs_success) {
SrsLiveConsumer* consumer_raw = NULL;
if ((err = live_source->create_consumer(consumer_raw)) != srs_success) {
return srs_error_wrap(err, "create consumer");
}
if ((err = live_source->consumer_dumps(consumer, false, false, true)) != srs_success) {
SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
if ((err = live_source->consumer_dumps(consumer.get(), false, false, true)) != srs_success) {
return srs_error_wrap(err, "dumps consumer");
}
SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream_cache();
SrsAutoFree(SrsPithyPrint, pprint);
SrsUniquePtr<SrsPithyPrint> pprint(SrsPithyPrint::create_http_stream_cache());
SrsMessageArray msgs(SRS_PERF_MW_MSGS);
// set the queue size, which used for max cache.
@ -647,7 +647,7 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
srs_error_t err = srs_success;
string enc_desc;
ISrsBufferEncoder* enc = NULL;
ISrsBufferEncoder* enc_raw = NULL;
srs_assert(entry);
bool drop_if_not_match = _srs_config->get_vhost_http_remux_drop_if_not_match(req->vhost);
@ -658,29 +658,29 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
if (srs_string_ends_with(entry->pattern, ".flv")) {
w->header()->set_content_type("video/x-flv");
enc_desc = "FLV";
enc = new SrsFlvStreamEncoder();
((SrsFlvStreamEncoder*)enc)->set_drop_if_not_match(drop_if_not_match);
((SrsFlvStreamEncoder*)enc)->set_has_audio(has_audio);
((SrsFlvStreamEncoder*)enc)->set_has_video(has_video);
((SrsFlvStreamEncoder*)enc)->set_guess_has_av(guess_has_av);
enc_raw = new SrsFlvStreamEncoder();
((SrsFlvStreamEncoder*)enc_raw)->set_drop_if_not_match(drop_if_not_match);
((SrsFlvStreamEncoder*)enc_raw)->set_has_audio(has_audio);
((SrsFlvStreamEncoder*)enc_raw)->set_has_video(has_video);
((SrsFlvStreamEncoder*)enc_raw)->set_guess_has_av(guess_has_av);
} else if (srs_string_ends_with(entry->pattern, ".aac")) {
w->header()->set_content_type("audio/x-aac");
enc_desc = "AAC";
enc = new SrsAacStreamEncoder();
enc_raw = new SrsAacStreamEncoder();
} else if (srs_string_ends_with(entry->pattern, ".mp3")) {
w->header()->set_content_type("audio/mpeg");
enc_desc = "MP3";
enc = new SrsMp3StreamEncoder();
enc_raw = new SrsMp3StreamEncoder();
} else if (srs_string_ends_with(entry->pattern, ".ts")) {
w->header()->set_content_type("video/MP2T");
enc_desc = "TS";
enc = new SrsTsStreamEncoder();
((SrsTsStreamEncoder*)enc)->set_has_audio(has_audio);
((SrsTsStreamEncoder*)enc)->set_has_video(has_video);
enc_raw = new SrsTsStreamEncoder();
((SrsTsStreamEncoder*)enc_raw)->set_has_audio(has_audio);
((SrsTsStreamEncoder*)enc_raw)->set_has_video(has_video);
} else {
return srs_error_new(ERROR_HTTP_LIVE_STREAM_EXT, "invalid pattern=%s", entry->pattern.c_str());
}
SrsAutoFree(ISrsBufferEncoder, enc);
SrsUniquePtr<ISrsBufferEncoder> enc(enc_raw);
// Enter chunked mode, because we didn't set the content-length.
w->write_header(SRS_CONSTS_HTTP_OK);
@ -691,18 +691,18 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
}
// create consumer of souce, ignore gop cache, use the audio gop cache.
SrsLiveConsumer* consumer = NULL;
SrsAutoFree(SrsLiveConsumer, consumer);
if ((err = live_source->create_consumer(consumer)) != srs_success) {
SrsLiveConsumer* consumer_raw = NULL;
if ((err = live_source->create_consumer(consumer_raw)) != srs_success) {
return srs_error_wrap(err, "create consumer");
}
if ((err = live_source->consumer_dumps(consumer, true, true, !enc->has_cache())) != srs_success) {
SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
if ((err = live_source->consumer_dumps(consumer.get(), true, true, !enc->has_cache())) != srs_success) {
return srs_error_wrap(err, "dumps consumer");
}
SrsPithyPrint* pprint = SrsPithyPrint::create_http_stream();
SrsAutoFree(SrsPithyPrint, pprint);
SrsUniquePtr<SrsPithyPrint> pprint(SrsPithyPrint::create_http_stream());
SrsMessageArray msgs(SRS_PERF_MW_MSGS);
// Use receive thread to accept the close event to avoid FD leak.
@ -718,22 +718,21 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
// if gop cache enabled for encoder, dump to consumer.
if (enc->has_cache()) {
if ((err = enc->dump_cache(consumer, live_source->jitter())) != srs_success) {
if ((err = enc->dump_cache(consumer.get(), live_source->jitter())) != srs_success) {
return srs_error_wrap(err, "encoder dump cache");
}
}
// Try to use fast flv encoder, remember that it maybe NULL.
SrsFlvStreamEncoder* ffe = dynamic_cast<SrsFlvStreamEncoder*>(enc);
SrsFlvStreamEncoder* ffe = dynamic_cast<SrsFlvStreamEncoder*>(enc.get());
// Note that the handler of hc now is hxc.
SrsHttpxConn* hxc = dynamic_cast<SrsHttpxConn*>(hc->handler());
srs_assert(hxc);
// Start a thread to receive all messages from client, then drop them.
SrsHttpRecvThread* trd = new SrsHttpRecvThread(hxc);
SrsAutoFree(SrsHttpRecvThread, trd);
SrsUniquePtr<SrsHttpRecvThread> trd(new SrsHttpRecvThread(hxc));
if ((err = trd->start()) != srs_success) {
return srs_error_wrap(err, "start recv thread");
}
@ -777,7 +776,7 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
if (ffe) {
err = ffe->write_tags(msgs.msgs, count);
} else {
err = streaming_send_messages(enc, msgs.msgs, count);
err = streaming_send_messages(enc.get(), msgs.msgs, count);
}
// TODO: FIXME: Update the stat.
@ -809,9 +808,8 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage* r)
// Create request to report for the specified connection.
SrsHttpMessage* hr = dynamic_cast<SrsHttpMessage*>(r);
SrsRequest* nreq = hr->to_request(req->vhost);
SrsAutoFree(SrsRequest, nreq);
SrsUniquePtr<SrsRequest> nreq(hr->to_request(req->vhost));
// the http hooks will cause context switch,
// so we must copy all hooks for the on_connect may freed.
// @see https://github.com/ossrs/srs/issues/475
@ -829,7 +827,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage* r)
for (int i = 0; i < (int)hooks.size(); i++) {
std::string url = hooks.at(i);
if ((err = SrsHttpHooks::on_play(url, nreq)) != srs_success) {
if ((err = SrsHttpHooks::on_play(url, nreq.get())) != srs_success) {
return srs_error_wrap(err, "http on_play %s", url.c_str());
}
}
@ -845,9 +843,8 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage* r)
// Create request to report for the specified connection.
SrsHttpMessage* hr = dynamic_cast<SrsHttpMessage*>(r);
SrsRequest* nreq = hr->to_request(req->vhost);
SrsAutoFree(SrsRequest, nreq);
SrsUniquePtr<SrsRequest> nreq(hr->to_request(req->vhost));
// the http hooks will cause context switch,
// so we must copy all hooks for the on_connect may freed.
// @see https://github.com/ossrs/srs/issues/475
@ -866,7 +863,7 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage* r)
for (int i = 0; i < (int)hooks.size(); i++) {
std::string url = hooks.at(i);
SrsHttpHooks::on_stop(url, nreq);
SrsHttpHooks::on_stop(url, nreq.get());
}
return;
@ -1063,15 +1060,11 @@ void SrsHttpStreamServer::http_unmount(SrsRequest* r)
}
// Free all HTTP resources.
SrsLiveEntry* entry = it->second;
SrsAutoFree(SrsLiveEntry, entry);
SrsUniquePtr<SrsLiveEntry> entry(it->second);
streamHandlers.erase(it);
SrsLiveStream* stream = entry->stream;
SrsAutoFree(SrsLiveStream, stream);
SrsBufferCache* cache = entry->cache;
SrsAutoFree(SrsBufferCache, cache);
SrsUniquePtr<SrsLiveStream> stream(entry->stream);
SrsUniquePtr<SrsBufferCache> cache(entry->cache);
// Notify cache and stream to stop.
if (stream->entry) stream->entry->enabled = false;
@ -1088,7 +1081,7 @@ void SrsHttpStreamServer::http_unmount(SrsRequest* r)
// Unmount the HTTP handler, which will free the entry. Note that we must free it after cache and
// stream stopped for it uses it.
mux.unhandle(entry->mount, stream);
mux.unhandle(entry->mount, stream.get());
srs_trace("http: unmount flv stream for sid=%s, i=%d", sid.c_str(), i);
}
@ -1170,9 +1163,8 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandle
srs_assert(hreq);
// hijack for entry.
SrsRequest* r = hreq->to_request(vhost->arg0());
SrsAutoFree(SrsRequest, r);
SrsUniquePtr<SrsRequest> r(hreq->to_request(vhost->arg0()));
std::string sid = r->get_stream_url();
// check whether the http remux is enabled,
// for example, user disable the http flv then reload.
@ -1189,7 +1181,7 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandle
}
SrsSharedPtr<SrsLiveSource> live_source;
if ((err = _srs_sources->fetch_or_create(r, server, live_source)) != srs_success) {
if ((err = _srs_sources->fetch_or_create(r.get(), server, live_source)) != srs_success) {
return srs_error_wrap(err, "source create");
}
srs_assert(live_source.get() != NULL);
@ -1200,7 +1192,7 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandle
live_source->set_gop_cache_max_frames(gcmf);
// create http streaming handler.
if ((err = http_mount(r)) != srs_success) {
if ((err = http_mount(r.get())) != srs_success) {
return srs_error_wrap(err, "http mount");
}