2017-08-20 14:53:25 +00:00
|
|
|
//
|
|
|
|
// Sleeper.h
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 20/08/2017.
|
2018-05-13 19:19:52 +00:00
|
|
|
// Copyright 2017 Thomas Harte. All rights reserved.
|
2017-08-20 14:53:25 +00:00
|
|
|
//
|
|
|
|
|
2017-08-20 15:54:54 +00:00
|
|
|
#ifndef Sleeper_hpp
|
|
|
|
#define Sleeper_hpp
|
2017-08-20 14:53:25 +00:00
|
|
|
|
|
|
|
/*!
|
2018-05-13 19:34:31 +00:00
|
|
|
A sleeper is any component that sometimes requires a clock but at other times is 'asleep', i.e. is not doing
|
2017-08-20 14:53:25 +00:00
|
|
|
any clock-derived work, so needn't receive a clock. A disk controller is an archetypal example.
|
|
|
|
|
|
|
|
A sleeper will signal sleeps and wakes to an observer.
|
|
|
|
|
|
|
|
This is intended to allow for performance improvements to machines with components that can sleep. The observer
|
|
|
|
callout is virtual so the intended use case is that a machine holds a component that might sleep. Its transitions
|
|
|
|
into and out of sleep are sufficiently infrequent that a virtual call to announce them costs sufficiently little that
|
|
|
|
the saved ::run_fors add up to a substantial amount.
|
|
|
|
|
|
|
|
By convention, sleeper components must be willing to accept ::run_for even after announcing sleep. It's a hint,
|
|
|
|
not a command.
|
|
|
|
*/
|
|
|
|
class Sleeper {
|
|
|
|
public:
|
|
|
|
Sleeper() : sleep_observer_(nullptr) {}
|
|
|
|
|
|
|
|
class SleepObserver {
|
|
|
|
public:
|
|
|
|
/// Called to inform an observer that the component @c component has either gone to sleep or become awake.
|
2018-04-29 21:51:10 +00:00
|
|
|
virtual void set_component_is_sleeping(Sleeper *component, bool is_sleeping) = 0;
|
2017-08-20 14:53:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Registers @c observer as the new sleep observer;
|
|
|
|
void set_sleep_observer(SleepObserver *observer) {
|
2017-08-20 15:54:54 +00:00
|
|
|
sleep_observer_ = observer;
|
2017-08-20 14:53:25 +00:00
|
|
|
}
|
|
|
|
|
2017-08-20 15:54:54 +00:00
|
|
|
/// @returns @c true if the component is currently sleeping; @c false otherwise.
|
|
|
|
virtual bool is_sleeping() = 0;
|
|
|
|
|
2017-08-20 14:53:25 +00:00
|
|
|
protected:
|
|
|
|
/// Provided for subclasses; send sleep announcements to the sleep_observer_.
|
|
|
|
SleepObserver *sleep_observer_;
|
2017-08-20 15:54:54 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
Provided for subclasses; call this whenever is_sleeping might have changed, and the observer will be notified,
|
|
|
|
if one exists.
|
|
|
|
|
|
|
|
@c is_sleeping will be called only if there is an observer.
|
|
|
|
*/
|
|
|
|
void update_sleep_observer() {
|
|
|
|
if(!sleep_observer_) return;
|
|
|
|
sleep_observer_->set_component_is_sleeping(this, is_sleeping());
|
|
|
|
}
|
2017-08-20 14:53:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* Sleeper_h */
|