| 2526 | } |
| 2527 | |
| 2528 | Stream *Stream::GetOrCreateSubStream() { |
| 2529 | absl::MutexLock lock(&mu_); |
| 2530 | |
| 2531 | // Look for the first reusable sub_stream that is ok, dropping !ok sub_streams |
| 2532 | // we encounter along the way. |
| 2533 | for (int64 index = 0; index < sub_streams_.size();) { |
| 2534 | std::pair<std::unique_ptr<Stream>, bool> &pair = sub_streams_[index]; |
| 2535 | if (pair.second) { |
| 2536 | // The sub_stream is reusable. |
| 2537 | Stream *sub_stream = pair.first.get(); |
| 2538 | if (sub_stream->ok()) { |
| 2539 | VLOG(1) << DebugStreamPointers() << " reusing sub_stream " |
| 2540 | << sub_stream->DebugStreamPointers(); |
| 2541 | pair.second = false; |
| 2542 | return sub_stream; |
| 2543 | } |
| 2544 | |
| 2545 | // The stream is reusable and not ok. Streams have a monotonic state |
| 2546 | // machine; the stream will remain in !ok forever. Swap it with the last |
| 2547 | // stream and pop it off. |
| 2548 | const int64 last = sub_streams_.size() - 1; |
| 2549 | if (index != last) { |
| 2550 | std::swap(pair, sub_streams_[last]); |
| 2551 | } |
| 2552 | sub_streams_.pop_back(); |
| 2553 | VLOG(1) << DebugStreamPointers() << " dropped !ok sub_stream " |
| 2554 | << sub_stream->DebugStreamPointers(); |
| 2555 | } else { |
| 2556 | // The sub_stream is not reusable, move on to the next one. |
| 2557 | ++index; |
| 2558 | } |
| 2559 | } |
| 2560 | |
| 2561 | // No streams are reusable; create a new stream. |
| 2562 | sub_streams_.emplace_back(std::unique_ptr<Stream>{new Stream{parent_}}, |
| 2563 | false); |
| 2564 | Stream *sub_stream = sub_streams_.back().first.get(); |
| 2565 | sub_stream->Init(); |
| 2566 | if (!sub_stream->ok_) { |
| 2567 | LOG(ERROR) << "sub-stream failed to be initialized"; |
| 2568 | } |
| 2569 | VLOG(1) << DebugStreamPointers() << " created new sub_stream " |
| 2570 | << sub_stream->DebugStreamPointers(); |
| 2571 | |
| 2572 | return sub_stream; |
| 2573 | } |
| 2574 | |
| 2575 | void Stream::ReturnSubStream(Stream *sub_stream) { |
| 2576 | absl::MutexLock lock(&mu_); |