修改pods
This commit is contained in:
296
Pods/abseil/absl/log/internal/log_sink_set.cc
generated
Normal file
296
Pods/abseil/absl/log/internal/log_sink_set.cc
generated
Normal file
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// Copyright 2022 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/log/internal/log_sink_set.h"
|
||||
|
||||
#ifndef ABSL_HAVE_THREAD_LOCAL
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/call_once.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/log_severity.h"
|
||||
#include "absl/base/no_destructor.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/cleanup/cleanup.h"
|
||||
#include "absl/log/globals.h"
|
||||
#include "absl/log/internal/config.h"
|
||||
#include "absl/log/internal/globals.h"
|
||||
#include "absl/log/log_entry.h"
|
||||
#include "absl/log/log_sink.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/types/span.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace log_internal {
|
||||
namespace {
|
||||
|
||||
// Returns a mutable reference to a thread-local variable that should be true if
|
||||
// a globally-registered `LogSink`'s `Send()` is currently being invoked on this
|
||||
// thread.
|
||||
bool& ThreadIsLoggingStatus() {
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
ABSL_CONST_INIT thread_local bool thread_is_logging = false;
|
||||
return thread_is_logging;
|
||||
#else
|
||||
ABSL_CONST_INIT static pthread_key_t thread_is_logging_key;
|
||||
static const bool unused = [] {
|
||||
if (pthread_key_create(&thread_is_logging_key, [](void* data) {
|
||||
delete reinterpret_cast<bool*>(data);
|
||||
})) {
|
||||
perror("pthread_key_create failed!");
|
||||
abort();
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
(void)unused; // Fixes -wunused-variable warning
|
||||
bool* thread_is_logging_ptr =
|
||||
reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));
|
||||
|
||||
if (ABSL_PREDICT_FALSE(!thread_is_logging_ptr)) {
|
||||
thread_is_logging_ptr = new bool{false};
|
||||
if (pthread_setspecific(thread_is_logging_key, thread_is_logging_ptr)) {
|
||||
perror("pthread_setspecific failed");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return *thread_is_logging_ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
class StderrLogSink final : public LogSink {
|
||||
public:
|
||||
~StderrLogSink() override = default;
|
||||
|
||||
void Send(const absl::LogEntry& entry) override {
|
||||
if (entry.log_severity() < absl::StderrThreshold() &&
|
||||
absl::log_internal::IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ABSL_CONST_INIT static absl::once_flag warn_if_not_initialized;
|
||||
absl::call_once(warn_if_not_initialized, []() {
|
||||
if (absl::log_internal::IsInitialized()) return;
|
||||
const char w[] =
|
||||
"WARNING: All log messages before absl::InitializeLog() is called"
|
||||
" are written to STDERR\n";
|
||||
absl::log_internal::WriteToStderr(w, absl::LogSeverity::kWarning);
|
||||
});
|
||||
|
||||
if (!entry.stacktrace().empty()) {
|
||||
absl::log_internal::WriteToStderr(entry.stacktrace(),
|
||||
entry.log_severity());
|
||||
} else {
|
||||
// TODO(b/226937039): do this outside else condition once we avoid
|
||||
// ReprintFatalMessage
|
||||
absl::log_internal::WriteToStderr(
|
||||
entry.text_message_with_prefix_and_newline(), entry.log_severity());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
class AndroidLogSink final : public LogSink {
|
||||
public:
|
||||
~AndroidLogSink() override = default;
|
||||
|
||||
void Send(const absl::LogEntry& entry) override {
|
||||
const int level = AndroidLogLevel(entry);
|
||||
const char* const tag = GetAndroidNativeTag();
|
||||
__android_log_write(level, tag,
|
||||
entry.text_message_with_prefix_and_newline_c_str());
|
||||
if (entry.log_severity() == absl::LogSeverity::kFatal)
|
||||
__android_log_write(ANDROID_LOG_FATAL, tag, "terminating.\n");
|
||||
}
|
||||
|
||||
private:
|
||||
static int AndroidLogLevel(const absl::LogEntry& entry) {
|
||||
switch (entry.log_severity()) {
|
||||
case absl::LogSeverity::kFatal:
|
||||
return ANDROID_LOG_FATAL;
|
||||
case absl::LogSeverity::kError:
|
||||
return ANDROID_LOG_ERROR;
|
||||
case absl::LogSeverity::kWarning:
|
||||
return ANDROID_LOG_WARN;
|
||||
default:
|
||||
if (entry.verbosity() >= 2) return ANDROID_LOG_VERBOSE;
|
||||
if (entry.verbosity() == 1) return ANDROID_LOG_DEBUG;
|
||||
return ANDROID_LOG_INFO;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // !defined(__ANDROID__)
|
||||
|
||||
#if defined(_WIN32)
|
||||
class WindowsDebuggerLogSink final : public LogSink {
|
||||
public:
|
||||
~WindowsDebuggerLogSink() override = default;
|
||||
|
||||
void Send(const absl::LogEntry& entry) override {
|
||||
if (entry.log_severity() < absl::StderrThreshold() &&
|
||||
absl::log_internal::IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
::OutputDebugStringA(entry.text_message_with_prefix_and_newline_c_str());
|
||||
}
|
||||
};
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
class GlobalLogSinkSet final {
|
||||
public:
|
||||
GlobalLogSinkSet() {
|
||||
#if defined(__myriad2__) || defined(__Fuchsia__)
|
||||
// myriad2 and Fuchsia do not log to stderr by default.
|
||||
#else
|
||||
static absl::NoDestructor<StderrLogSink> stderr_log_sink;
|
||||
AddLogSink(stderr_log_sink.get());
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
static absl::NoDestructor<AndroidLogSink> android_log_sink;
|
||||
AddLogSink(android_log_sink.get());
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
static absl::NoDestructor<WindowsDebuggerLogSink> debugger_log_sink;
|
||||
AddLogSink(debugger_log_sink.get());
|
||||
#endif // !defined(_WIN32)
|
||||
}
|
||||
|
||||
void LogToSinks(const absl::LogEntry& entry,
|
||||
absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only)
|
||||
ABSL_LOCKS_EXCLUDED(guard_) {
|
||||
SendToSinks(entry, extra_sinks);
|
||||
|
||||
if (!extra_sinks_only) {
|
||||
if (ThreadIsLoggingToLogSink()) {
|
||||
absl::log_internal::WriteToStderr(
|
||||
entry.text_message_with_prefix_and_newline(), entry.log_severity());
|
||||
} else {
|
||||
absl::ReaderMutexLock global_sinks_lock(&guard_);
|
||||
ThreadIsLoggingStatus() = true;
|
||||
// Ensure the "thread is logging" status is reverted upon leaving the
|
||||
// scope even in case of exceptions.
|
||||
auto status_cleanup =
|
||||
absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
|
||||
SendToSinks(entry, absl::MakeSpan(sinks_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
|
||||
{
|
||||
absl::WriterMutexLock global_sinks_lock(&guard_);
|
||||
auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
|
||||
if (pos == sinks_.end()) {
|
||||
sinks_.push_back(sink);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ABSL_INTERNAL_LOG(FATAL, "Duplicate log sinks are not supported");
|
||||
}
|
||||
|
||||
void RemoveLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
|
||||
{
|
||||
absl::WriterMutexLock global_sinks_lock(&guard_);
|
||||
auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
|
||||
if (pos != sinks_.end()) {
|
||||
sinks_.erase(pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ABSL_INTERNAL_LOG(FATAL, "Mismatched log sink being removed");
|
||||
}
|
||||
|
||||
void FlushLogSinks() ABSL_LOCKS_EXCLUDED(guard_) {
|
||||
if (ThreadIsLoggingToLogSink()) {
|
||||
// The thread_local condition demonstrates that we're already holding the
|
||||
// lock in order to iterate over `sinks_` for dispatch. The thread-safety
|
||||
// annotations don't know this, so we use `ABSL_NO_THREAD_SAFETY_ANALYSIS`
|
||||
guard_.AssertReaderHeld();
|
||||
FlushLogSinksLocked();
|
||||
} else {
|
||||
absl::ReaderMutexLock global_sinks_lock(&guard_);
|
||||
// In case if LogSink::Flush overload decides to log
|
||||
ThreadIsLoggingStatus() = true;
|
||||
// Ensure the "thread is logging" status is reverted upon leaving the
|
||||
// scope even in case of exceptions.
|
||||
auto status_cleanup =
|
||||
absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
|
||||
FlushLogSinksLocked();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void FlushLogSinksLocked() ABSL_SHARED_LOCKS_REQUIRED(guard_) {
|
||||
for (absl::LogSink* sink : sinks_) {
|
||||
sink->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper routine for LogToSinks.
|
||||
static void SendToSinks(const absl::LogEntry& entry,
|
||||
absl::Span<absl::LogSink*> sinks) {
|
||||
for (absl::LogSink* sink : sinks) {
|
||||
sink->Send(entry);
|
||||
}
|
||||
}
|
||||
|
||||
using LogSinksSet = std::vector<absl::LogSink*>;
|
||||
absl::Mutex guard_;
|
||||
LogSinksSet sinks_ ABSL_GUARDED_BY(guard_);
|
||||
};
|
||||
|
||||
// Returns reference to the global LogSinks set.
|
||||
GlobalLogSinkSet& GlobalSinks() {
|
||||
static absl::NoDestructor<GlobalLogSinkSet> global_sinks;
|
||||
return *global_sinks;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); }
|
||||
|
||||
void LogToSinks(const absl::LogEntry& entry,
|
||||
absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only) {
|
||||
log_internal::GlobalSinks().LogToSinks(entry, extra_sinks, extra_sinks_only);
|
||||
}
|
||||
|
||||
void AddLogSink(absl::LogSink* sink) {
|
||||
log_internal::GlobalSinks().AddLogSink(sink);
|
||||
}
|
||||
|
||||
void RemoveLogSink(absl::LogSink* sink) {
|
||||
log_internal::GlobalSinks().RemoveLogSink(sink);
|
||||
}
|
||||
|
||||
void FlushLogSinks() { log_internal::GlobalSinks().FlushLogSinks(); }
|
||||
|
||||
} // namespace log_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
Reference in New Issue
Block a user