| 73 | } |
| 74 | |
| 75 | QueueStatus LifoServiceQueue::Put(InboundCall* call, |
| 76 | std::optional<InboundCall*>* evicted) { |
| 77 | std::unique_lock<simple_spinlock> l(lock_); |
| 78 | if (PREDICT_FALSE(shutdown_)) { |
| 79 | return QUEUE_SHUTDOWN; |
| 80 | } |
| 81 | |
| 82 | DCHECK(!(waiting_consumers_.size() > 0 && queue_.size() > 0)); |
| 83 | |
| 84 | // fast path |
| 85 | if (queue_.empty() && waiting_consumers_.size() > 0) { |
| 86 | auto consumer = waiting_consumers_[waiting_consumers_.size() - 1]; |
| 87 | waiting_consumers_.pop_back(); |
| 88 | // Notify condition var(and wake up consumer thread) takes time, |
| 89 | // so put it out of spinlock scope. |
| 90 | l.unlock(); |
| 91 | consumer->Post(call); |
| 92 | return QUEUE_SUCCESS; |
| 93 | } |
| 94 | |
| 95 | if (PREDICT_FALSE(queue_.size() >= max_queue_size_)) { |
| 96 | // eviction |
| 97 | DCHECK_EQ(queue_.size(), max_queue_size_); |
| 98 | auto it = queue_.end(); |
| 99 | --it; |
| 100 | if (DeadlineLess(*it, call)) { |
| 101 | return QUEUE_FULL; |
| 102 | } |
| 103 | |
| 104 | *evicted = *it; |
| 105 | queue_.erase(it); |
| 106 | } |
| 107 | |
| 108 | queue_.insert(call); |
| 109 | return QUEUE_SUCCESS; |
| 110 | } |
| 111 | |
| 112 | void LifoServiceQueue::Shutdown() { |
| 113 | std::lock_guard<simple_spinlock> l(lock_); |