tryEnterIdleMode instructs the channel to enter idle mode. But before that, it performs a last minute check to ensure that no new RPC has come in, making the channel active. checkActivity controls if a check for RPC activity, since the last time the idle_timeout fired, is made. Return value indicat
(checkActivity bool)
| 148 | // |
| 149 | // Holds idleMu which ensures mutual exclusion with exitIdleMode. |
| 150 | func (m *Manager) tryEnterIdleMode(checkActivity bool) bool { |
| 151 | // Setting the activeCallsCount to -math.MaxInt32 indicates to OnCallBegin() |
| 152 | // that the channel is either in idle mode or is trying to get there. |
| 153 | if !atomic.CompareAndSwapInt32(&m.activeCallsCount, 0, -math.MaxInt32) { |
| 154 | // This CAS operation can fail if an RPC started after we checked for |
| 155 | // activity in the timer handler, or one was ongoing from before the |
| 156 | // last time the timer fired, or if a test is attempting to enter idle |
| 157 | // mode without checking. In all cases, abort going into idle mode. |
| 158 | return false |
| 159 | } |
| 160 | // N.B. if we fail to enter idle mode after this, we must re-add |
| 161 | // math.MaxInt32 to m.activeCallsCount. |
| 162 | |
| 163 | m.idleMu.Lock() |
| 164 | defer m.idleMu.Unlock() |
| 165 | |
| 166 | if atomic.LoadInt32(&m.activeCallsCount) != -math.MaxInt32 { |
| 167 | // We raced and lost to a new RPC. Very rare, but stop entering idle. |
| 168 | atomic.AddInt32(&m.activeCallsCount, math.MaxInt32) |
| 169 | return false |
| 170 | } |
| 171 | if checkActivity && atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 { |
| 172 | // A very short RPC could have come in (and also finished) after we |
| 173 | // checked for calls count and activity in handleIdleTimeout(), but |
| 174 | // before the CAS operation. So, we need to check for activity again. |
| 175 | atomic.AddInt32(&m.activeCallsCount, math.MaxInt32) |
| 176 | return false |
| 177 | } |
| 178 | |
| 179 | // No new RPCs have come in since we set the active calls count value to |
| 180 | // -math.MaxInt32. And since we have the lock, it is safe to enter idle mode |
| 181 | // unconditionally now. |
| 182 | m.cc.EnterIdleMode() |
| 183 | m.actuallyIdle = true |
| 184 | return true |
| 185 | } |
| 186 | |
| 187 | // EnterIdleModeForTesting instructs the channel to enter idle mode. |
| 188 | func (m *Manager) EnterIdleModeForTesting() { |
no test coverage detected