| 2332 | : _parent(parent) {} |
| 2333 | |
| 2334 | void RtmpRetryingClientStream::Recreate() { |
| 2335 | butil::intrusive_ptr<RtmpStreamBase> sub_stream; |
| 2336 | _sub_stream_creator->NewSubStream(new RetryingClientMessageHandler(this), &sub_stream); |
| 2337 | butil::intrusive_ptr<RtmpStreamBase> old_sub_stream; |
| 2338 | bool destroying = false; |
| 2339 | { |
| 2340 | BAIDU_SCOPED_LOCK(_stream_mutex); |
| 2341 | // Need to check _destroying to avoid setting the new sub_stream to a |
| 2342 | // destroying retrying stream. |
| 2343 | // Note: the load of _destroying and the setting of _using_sub_stream |
| 2344 | // must be in the same lock, otherwise current bthread may be scheduled |
| 2345 | // and Destroy() may be called, making new sub_stream leaked. |
| 2346 | destroying = _destroying.load(butil::memory_order_relaxed); |
| 2347 | if (!destroying) { |
| 2348 | _using_sub_stream.swap(old_sub_stream); |
| 2349 | _using_sub_stream = sub_stream; |
| 2350 | _changed_stream = true; |
| 2351 | } |
| 2352 | } |
| 2353 | if (old_sub_stream) { |
| 2354 | old_sub_stream->Destroy(); |
| 2355 | } |
| 2356 | if (destroying) { |
| 2357 | sub_stream->Destroy(); |
| 2358 | return; |
| 2359 | } |
| 2360 | _last_creation_time_us = butil::gettimeofday_us(); |
| 2361 | // If Init() of sub_stream is called before setting _using_sub_stream, |
| 2362 | // OnStop() may happen before _using_sub_stream is set and the stopped |
| 2363 | // stream is wrongly left in the variable. |
| 2364 | |
| 2365 | _sub_stream_creator->LaunchSubStream(sub_stream.get(), &_options); |
| 2366 | } |
| 2367 | |
| 2368 | void RtmpRetryingClientStream::OnRecreateTimer(void* arg) { |
| 2369 | // Hold the referenced stream. |
no test coverage detected