blob: 7cedee633533751d7d5fdd5f686381b72683522a [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_
#define QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_export.h"
#include "common/platform/api/quiche_logging.h"
namespace quic {
// QuicConnectionTracer is responsible for emit trace messages for a single
// QuicConnection.
// QuicConnectionTracer is part of the QuicConnectionContext.
class QUIC_EXPORT_PRIVATE QuicConnectionTracer {
public:
virtual ~QuicConnectionTracer() = default;
// Emit a trace message from a string literal. The trace may simply remember
// the address of the literal in this function and read it at a later time.
virtual void PrintLiteral(const char* literal) = 0;
// Emit a trace message from a string_view. Unlike PrintLiteral, this function
// will not read |s| after it returns.
virtual void PrintString(absl::string_view s) = 0;
// Emit a trace message from printf-style arguments.
template <typename... Args>
void Printf(const absl::FormatSpec<Args...>& format, const Args&... args) {
std::string s = absl::StrFormat(format, args...);
PrintString(s);
}
private:
friend class QuicConnectionContextSwitcher;
// Called by QuicConnectionContextSwitcher, when |this| becomes the current
// thread's QUIC connection tracer.
//
// Activate/Deactivate are only called by QuicConnectionContextSwitcher's
// constructor/destructor, they always come in pairs.
virtual void Activate() {}
// Called by QuicConnectionContextSwitcher, when |this| stops from being the
// current thread's QUIC connection tracer.
//
// Activate/Deactivate are only called by QuicConnectionContextSwitcher's
// constructor/destructor, they always come in pairs.
virtual void Deactivate() {}
};
// QuicConnectionContext is a per-QuicConnection context that includes
// facilities useable by any part of a QuicConnection. A QuicConnectionContext
// is owned by a QuicConnection.
//
// The 'top-level' QuicConnection functions are responsible for maintaining the
// thread-local QuicConnectionContext pointer, such that any function called by
// them(directly or indirectly) can access the context.
//
// Like QuicConnection, all facilities in QuicConnectionContext are assumed to
// be called from a single thread at a time, they are NOT thread-safe.
struct QUIC_EXPORT_PRIVATE QuicConnectionContext final {
// Get the context on the current executing thread. nullptr if the current
// function is not called from a 'top-level' QuicConnection function.
static QuicConnectionContext* Current();
std::unique_ptr<QuicConnectionTracer> tracer;
};
// QuicConnectionContextSwitcher is a RAII object used for maintaining the
// thread-local QuicConnectionContext pointer.
class QUIC_EXPORT_PRIVATE QuicConnectionContextSwitcher final {
public:
// The constructor switches from QuicConnectionContext::Current() to
// |new_context|.
explicit QuicConnectionContextSwitcher(QuicConnectionContext* new_context);
// The destructor switches from QuicConnectionContext::Current() back to the
// old context.
~QuicConnectionContextSwitcher();
private:
QuicConnectionContext* old_context_;
};
// Emit a trace message from a string literal to the current tracer(if any).
inline void QUIC_TRACELITERAL(const char* literal) {
QuicConnectionContext* current = QuicConnectionContext::Current();
if (current && current->tracer) {
current->tracer->PrintLiteral(literal);
}
}
// Emit a trace message from a string_view to the current tracer(if any).
inline void QUIC_TRACESTRING(absl::string_view s) {
QuicConnectionContext* current = QuicConnectionContext::Current();
if (current && current->tracer) {
current->tracer->PrintString(s);
}
}
// Emit a trace message from printf-style arguments to the current tracer(if
// any).
template <typename... Args>
void QUIC_TRACEPRINTF(const absl::FormatSpec<Args...>& format,
const Args&... args) {
QuicConnectionContext* current = QuicConnectionContext::Current();
if (current && current->tracer) {
current->tracer->Printf(format, args...);
}
}
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_