trace-core: add a function to rebuild cached interest (#1039)

## Motivation

Currently, `tokio-trace-core` permits `Subscriber`s to indicate that
they are "always", "sometimes", or "never" interested in a particular
callsite. When "always" or "never" is returned, then the interest is
cached and the subscriber will not be asked again about that callsite.
This is much more efficient than requiring the filter to be re-evaluated
every time the callsite is hit.

However, if a subscriber wishes to change its filter configuration
dynamically at runtime, it cannot benefit from this caching. Instead, it
must always return `Interest::sometimes`.  Even when filters change very
infrequently, they must still always be re-evaluated every time.

In order to support a use-case where subscribers may change their filter
configuration at runtime (e.g. tokio-rs/tokio-trace-nursery#42),
but do so infrequently, we should introducing a new function to
invalidate the cached interest.

## Solution

This branch adds a new function in the `callsite` module, called
`rebuild_interest_cache`, that will invalidate and rebuild all cached
interest.

## Breaking Change

In order to fix a race condition that could occur when rebuilding
interest caches using `clear_interest` and `add_interest`, these methods
have been replaced by a new `set_interest` method. `set_interest` should
have the semantics of atomically replacing the previous cached interest,
so that the callsite does not enter a temporary state where it has no
interest.

Closes #1038

Co-Authored-By: yaahallo <[email protected]>
This commit is contained in:
Jane Lusby
2019-04-10 13:51:05 -07:00
committed by Eliza Weisman
parent 7ae010f0f3
commit b4fe517a16
12 changed files with 321 additions and 237 deletions
+5 -18
View File
@@ -1274,28 +1274,15 @@ macro_rules! callsite {
}
}
impl callsite::Callsite for MyCallsite {
fn add_interest(&self, interest: Interest) {
let current_interest = self.interest();
fn set_interest(&self, interest: Interest) {
let interest = match () {
// If the added interest is `never()`, don't change anything
// — either a different subscriber added a higher
// interest, which we want to preserve, or the interest is 0
// anyway (as it's initialized to 0).
_ if interest.is_never() => return,
// If the interest is `sometimes()`, that overwrites a `never()`
// interest, but doesn't downgrade an `always()` interest.
_ if interest.is_sometimes() && current_interest.is_never() => 1,
// If the interest is `always()`, we overwrite the current
// interest, as always() is the highest interest level and
// should take precedent.
_ if interest.is_never() => 0,
_ if interest.is_always() => 2,
_ => return,
_ => 1,
};
INTEREST.store(interest, Ordering::Relaxed);
}
fn clear_interest(&self) {
INTEREST.store(0, Ordering::Relaxed);
INTEREST.store(interest, Ordering::SeqCst);
}
fn metadata(&self) -> &Metadata {
&META
}