1*05767d91SRobert Wu /* 2*05767d91SRobert Wu * Copyright 2016 The Android Open Source Project 3*05767d91SRobert Wu * 4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License"); 5*05767d91SRobert Wu * you may not use this file except in compliance with the License. 6*05767d91SRobert Wu * You may obtain a copy of the License at 7*05767d91SRobert Wu * 8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0 9*05767d91SRobert Wu * 10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software 11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS, 12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*05767d91SRobert Wu * See the License for the specific language governing permissions and 14*05767d91SRobert Wu * limitations under the License. 15*05767d91SRobert Wu */ 16*05767d91SRobert Wu 17*05767d91SRobert Wu #ifndef COMMON_MONOTONIC_COUNTER_H 18*05767d91SRobert Wu #define COMMON_MONOTONIC_COUNTER_H 19*05767d91SRobert Wu 20*05767d91SRobert Wu #include <cstdint> 21*05767d91SRobert Wu 22*05767d91SRobert Wu /** 23*05767d91SRobert Wu * Maintain a 64-bit monotonic counter. 24*05767d91SRobert Wu * Can be used to track a 32-bit counter that wraps or gets reset. 25*05767d91SRobert Wu * 26*05767d91SRobert Wu * Note that this is not atomic and has no interior locks. 27*05767d91SRobert Wu * A caller will need to provide their own exterior locking 28*05767d91SRobert Wu * if they need to use it from multiple threads. 29*05767d91SRobert Wu */ 30*05767d91SRobert Wu class MonotonicCounter { 31*05767d91SRobert Wu 32*05767d91SRobert Wu public: MonotonicCounter()33*05767d91SRobert Wu MonotonicCounter() {} ~MonotonicCounter()34*05767d91SRobert Wu virtual ~MonotonicCounter() {} 35*05767d91SRobert Wu 36*05767d91SRobert Wu /** 37*05767d91SRobert Wu * @return current value of the counter 38*05767d91SRobert Wu */ get()39*05767d91SRobert Wu int64_t get() const { 40*05767d91SRobert Wu return mCounter64; 41*05767d91SRobert Wu } 42*05767d91SRobert Wu 43*05767d91SRobert Wu /** 44*05767d91SRobert Wu * set the current value of the counter 45*05767d91SRobert Wu */ set(int64_t counter)46*05767d91SRobert Wu void set(int64_t counter) { 47*05767d91SRobert Wu mCounter64 = counter; 48*05767d91SRobert Wu } 49*05767d91SRobert Wu 50*05767d91SRobert Wu /** 51*05767d91SRobert Wu * Advance the counter if delta is positive. 52*05767d91SRobert Wu * @return current value of the counter 53*05767d91SRobert Wu */ increment(int64_t delta)54*05767d91SRobert Wu int64_t increment(int64_t delta) { 55*05767d91SRobert Wu if (delta > 0) { 56*05767d91SRobert Wu mCounter64 += delta; 57*05767d91SRobert Wu } 58*05767d91SRobert Wu return mCounter64; 59*05767d91SRobert Wu } 60*05767d91SRobert Wu 61*05767d91SRobert Wu /** 62*05767d91SRobert Wu * Advance the 64-bit counter if (current32 - previousCurrent32) > 0. 63*05767d91SRobert Wu * This can be used to convert a 32-bit counter that may be wrapping into 64*05767d91SRobert Wu * a monotonic 64-bit counter. 65*05767d91SRobert Wu * 66*05767d91SRobert Wu * This counter32 should NOT be allowed to advance by more than 0x7FFFFFFF between calls. 67*05767d91SRobert Wu * Think of the wrapping counter like a sine wave. If the frequency of the signal 68*05767d91SRobert Wu * is more than half the sampling rate (Nyquist rate) then you cannot measure it properly. 69*05767d91SRobert Wu * If the counter wraps around every 24 hours then we should measure it with a period 70*05767d91SRobert Wu * of less than 12 hours. 71*05767d91SRobert Wu * 72*05767d91SRobert Wu * @return current value of the 64-bit counter 73*05767d91SRobert Wu */ update32(int32_t counter32)74*05767d91SRobert Wu int64_t update32(int32_t counter32) { 75*05767d91SRobert Wu int32_t delta = counter32 - mCounter32; 76*05767d91SRobert Wu // protect against the mCounter64 going backwards 77*05767d91SRobert Wu if (delta > 0) { 78*05767d91SRobert Wu mCounter64 += delta; 79*05767d91SRobert Wu mCounter32 = counter32; 80*05767d91SRobert Wu } 81*05767d91SRobert Wu return mCounter64; 82*05767d91SRobert Wu } 83*05767d91SRobert Wu 84*05767d91SRobert Wu /** 85*05767d91SRobert Wu * Reset the stored value of the 32-bit counter. 86*05767d91SRobert Wu * This is used if your counter32 has been reset to zero. 87*05767d91SRobert Wu */ reset32()88*05767d91SRobert Wu void reset32() { 89*05767d91SRobert Wu mCounter32 = 0; 90*05767d91SRobert Wu } 91*05767d91SRobert Wu 92*05767d91SRobert Wu /** 93*05767d91SRobert Wu * Round 64-bit counter up to a multiple of the period. 94*05767d91SRobert Wu * 95*05767d91SRobert Wu * The period must be positive. 96*05767d91SRobert Wu * 97*05767d91SRobert Wu * @param period might be, for example, a buffer capacity 98*05767d91SRobert Wu */ roundUp64(int32_t period)99*05767d91SRobert Wu void roundUp64(int32_t period) { 100*05767d91SRobert Wu if (period > 0) { 101*05767d91SRobert Wu int64_t numPeriods = (mCounter64 + period - 1) / period; 102*05767d91SRobert Wu mCounter64 = numPeriods * period; 103*05767d91SRobert Wu } 104*05767d91SRobert Wu } 105*05767d91SRobert Wu 106*05767d91SRobert Wu private: 107*05767d91SRobert Wu int64_t mCounter64 = 0; 108*05767d91SRobert Wu int32_t mCounter32 = 0; 109*05767d91SRobert Wu }; 110*05767d91SRobert Wu 111*05767d91SRobert Wu 112*05767d91SRobert Wu #endif //COMMON_MONOTONIC_COUNTER_H 113