1 // Copyright 2021 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_EXT_FILTERS_CHANNEL_IDLE_IDLE_FILTER_STATE_H 16 #define GRPC_SRC_CORE_EXT_FILTERS_CHANNEL_IDLE_IDLE_FILTER_STATE_H 17 18 #include <grpc/support/port_platform.h> 19 #include <stdint.h> 20 21 #include <atomic> 22 23 namespace grpc_core { 24 25 // State machine for the idle filter. 26 // Keeps track of how many calls are in progress, whether there is a timer 27 // started, and whether we've seen calls since the previous timer fired. 28 class IdleFilterState { 29 public: 30 explicit IdleFilterState(bool start_timer); 31 ~IdleFilterState() = default; 32 33 IdleFilterState(const IdleFilterState&) = delete; 34 IdleFilterState& operator=(const IdleFilterState&) = delete; 35 36 // Increment the number of calls in progress. 37 void IncreaseCallCount(); 38 39 // Decrement the number of calls in progress. 40 // Return true if we reached idle with no timer started. 41 GRPC_MUST_USE_RESULT bool DecreaseCallCount(); 42 43 // Check if there's been any activity since the last timer check. 44 // If there was, reset the activity flag and return true to indicated that 45 // a new timer should be started. 46 // If there was not, reset the timer flag and return false - in this case 47 // we know that the channel is idle and has been for one full cycle. 48 GRPC_MUST_USE_RESULT bool CheckTimer(); 49 50 private: 51 // Bit in state_ indicating that the timer has been started. 52 static constexpr uintptr_t kTimerStarted = 1; 53 // Bit in state_ indicating that we've seen a call start or stop since the 54 // last timer. 55 static constexpr uintptr_t kCallsStartedSinceLastTimerCheck = 2; 56 // How much should we shift to get the number of calls in progress. 57 static constexpr uintptr_t kCallsInProgressShift = 2; 58 // How much to increment/decrement the state_ when a call is started/stopped. 59 // Ensures we don't clobber the preceding bits. 60 static constexpr uintptr_t kCallIncrement = uintptr_t{1} 61 << kCallsInProgressShift; 62 std::atomic<uintptr_t> state_; 63 }; 64 65 } // namespace grpc_core 66 67 #endif // GRPC_SRC_CORE_EXT_FILTERS_CHANNEL_IDLE_IDLE_FILTER_STATE_H 68