215 lines
8.6 KiB
C++
215 lines
8.6 KiB
C++
/**
|
|
* @file lldeadmantimer.h
|
|
* @brief Interface to a simple event timer with a deadman's switch
|
|
* @author monty@lindenlab.com
|
|
*
|
|
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2013, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#ifndef LL_DEADMANTIMER_H
|
|
#define LL_DEADMANTIMER_H
|
|
|
|
|
|
#include "linden_common.h"
|
|
|
|
#include "lltimer.h"
|
|
#include "llprocinfo.h"
|
|
|
|
|
|
/// @file lldeadmantimer.h
|
|
///
|
|
/// There are interesting user-experienced events in the viewer that
|
|
/// would seem to have well-defined start and stop points but which
|
|
/// actually lack such milestones in the code. Such events (like
|
|
/// time to load meshes after logging in, initial inventory load,
|
|
/// display name fetch) can be defined somewhat after-the-fact by
|
|
/// noticing when we no longer perform operations towards their
|
|
/// completion. This class is intended to help in such applications.
|
|
///
|
|
/// What it implements is a deadman's switch (also known as a
|
|
/// keepalive switch and a doorbell switch). The basic operation is
|
|
/// as follows:
|
|
///
|
|
/// * LLDeadmanTimer is instantiated with a horizon value in seconds,
|
|
/// one for each event of interest.
|
|
/// * When an event starts, @see start() is invoked to begin a
|
|
/// timing operation.
|
|
/// * As operations are performed in service of the event (issuing
|
|
/// HTTP requests, receiving responses), @see ringBell() is invoked
|
|
/// to inform the timer that the operation is still active.
|
|
/// * If the operation is canceled or otherwise terminated, @see
|
|
/// stop() can be called to end the timing operation.
|
|
/// * Concurrent with the ringBell() calls, the program makes
|
|
/// periodic (shorter than the horizon but not too short) calls
|
|
/// to @see isExpired() to see if the event has expired due to
|
|
/// either a stop() call or lack of activity (defined as a ringBell()
|
|
/// call in the previous 'horizon' seconds). If it has expired,
|
|
/// the caller also receives start, stop and count values for the
|
|
/// event which the application can then report in whatever manner
|
|
/// it sees fit.
|
|
/// * The timer becomes passive after an isExpired() call that returns
|
|
/// true. It can then be restarted with a new start() call.
|
|
///
|
|
/// Threading: Instances are not thread-safe. They also use
|
|
/// timing code from lltimer.h which is also unsafe.
|
|
///
|
|
/// Allocation: Not refcounted, may be stack or heap allocated.
|
|
///
|
|
|
|
class LL_COMMON_API LLDeadmanTimer
|
|
{
|
|
public:
|
|
/// Public types
|
|
|
|
/// Low-level time type chosen for compatibility with
|
|
/// LLTimer::getCurrentClockCount() which is the basis
|
|
/// of time operations in this class. This is likely
|
|
/// to change in a future version in a move to TSC-based
|
|
/// timing.
|
|
typedef U64 time_type;
|
|
|
|
public:
|
|
/// Construct and initialize an LLDeadmanTimer
|
|
///
|
|
/// @param horizon Time, in seconds, after the last @see ringBell()
|
|
/// call at which point the timer will consider itself
|
|
/// expired.
|
|
///
|
|
/// @param inc_cpu If true, gather system and user cpu stats while
|
|
/// running the timer. This does require more syscalls
|
|
/// during updates. If false, cpu usage data isn't
|
|
/// collected and will be zero if queried.
|
|
LLDeadmanTimer(F64 horizon, bool inc_cpu);
|
|
|
|
~LLDeadmanTimer()
|
|
{}
|
|
|
|
private:
|
|
LLDeadmanTimer(const LLDeadmanTimer &); // Not defined
|
|
void operator=(const LLDeadmanTimer &); // Not defined
|
|
|
|
public:
|
|
/// Get the current time. Zero-basis for this time
|
|
/// representation is not defined and is different on
|
|
/// different platforms. Do not attempt to compute
|
|
/// negative times relative to the first value returned,
|
|
/// there may not be enough 'front porch' on the range
|
|
/// to prevent wraparound.
|
|
///
|
|
/// Note: Implementation is expected to change in a
|
|
/// future release as well.
|
|
///
|
|
static time_type getNow();
|
|
|
|
/// Begin timing. If the timer is already active, it is reset
|
|
/// and timing begins now.
|
|
///
|
|
/// @param now Current time as returned by @see
|
|
/// LLTimer::getCurrentClockCount(). If zero,
|
|
/// method will lookup current time.
|
|
///
|
|
void start(time_type now);
|
|
|
|
/// End timing. Actively declare the end of the event independent
|
|
/// of the deadman's switch operation. @see isExpired() will return
|
|
/// true and appropriate values will be returned.
|
|
///
|
|
/// @param now Current time as returned by @see
|
|
/// LLTimer::getCurrentClockCount(). If zero,
|
|
/// method will lookup current time.
|
|
///
|
|
void stop(time_type now);
|
|
|
|
/// Declare that something interesting happened. This has two
|
|
/// effects on an unexpired-timer. 1) The expiration time
|
|
/// is extended for 'horizon' seconds after the 'now' value.
|
|
/// 2) An internal counter associated with the event is incremented
|
|
/// by the @ref count parameter. This count is returned via the
|
|
/// @see isExpired() method.
|
|
///
|
|
/// @param now Current time as returned by @see
|
|
/// LLTimer::getCurrentClockCount(). If zero,
|
|
/// method will lookup current time.
|
|
///
|
|
/// @param count Count of events to be associated with
|
|
/// this bell ringing.
|
|
///
|
|
void ringBell(time_type now, unsigned int count);
|
|
|
|
/// Checks the status of the timer. If the timer has expired,
|
|
/// also returns various timer-related stats. Unlike ringBell(),
|
|
/// does not extend the horizon, it only checks for expiration.
|
|
///
|
|
/// @param now Current time as returned by @see
|
|
/// LLTimer::getCurrentClockCount(). If zero,
|
|
/// method will lookup current time.
|
|
///
|
|
/// @param started If expired, the starting time of the event is
|
|
/// returned to the caller via this reference.
|
|
///
|
|
/// @param stopped If expired, the ending time of the event is
|
|
/// returned to the caller via this reference.
|
|
/// Ending time will be that provided in the
|
|
/// stop() method or the last ringBell() call
|
|
/// leading to expiration, whichever (stop() call
|
|
/// or notice of expiration) happened first.
|
|
///
|
|
/// @param count If expired, the number of ringBell() calls
|
|
/// made prior to expiration.
|
|
///
|
|
/// @param user_cpu Amount of CPU spent in user mode by the process
|
|
/// during the event. Value in microseconds and will
|
|
/// read zero if not enabled by the constructor.
|
|
///
|
|
/// @param sys_cpu Amount of CPU spent in system mode by the process.
|
|
///
|
|
/// @return true if the timer has expired, false otherwise.
|
|
/// If true, it also returns the started,
|
|
/// stopped and count values otherwise these are
|
|
/// left unchanged.
|
|
///
|
|
bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count,
|
|
U64 & user_cpu, U64 & sys_cpu);
|
|
|
|
/// Identical to the six-arugment form except it does without the
|
|
/// CPU time return if the caller isn't interested in it.
|
|
bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count);
|
|
|
|
protected:
|
|
time_type mHorizon;
|
|
bool mActive;
|
|
bool mDone;
|
|
time_type mStarted;
|
|
time_type mExpires;
|
|
time_type mStopped;
|
|
time_type mCount;
|
|
|
|
const bool mIncCPU; // Include CPU metrics in timer
|
|
LLProcInfo::time_type mUStartCPU;
|
|
LLProcInfo::time_type mUEndCPU;
|
|
LLProcInfo::time_type mSStartCPU;
|
|
LLProcInfo::time_type mSEndCPU;
|
|
};
|
|
|
|
|
|
#endif // LL_DEADMANTIMER_H
|