mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1174785 - Part 1: Add LogModule, LogModuleManager, and LazyLogModule. r=froydnj
The logging interface is moved to xpcom/base, a LogModule wrapper for PR_Log is added, a thread-safe LogModuleManager is added, and a LazyLogModule class used to lazily load log modules in a thread-safe manner is added.
This commit is contained in:
parent
a1e1611abe
commit
1e2da43ec5
@ -1254,6 +1254,8 @@ XRE_XPCShellMain(int argc, char** argv, char** envp)
|
||||
|
||||
NS_LogInit();
|
||||
|
||||
mozilla::LogModule::Init();
|
||||
|
||||
// A initializer to initialize histogram collection
|
||||
// used by telemetry.
|
||||
UniquePtr<base::StatisticsRecorder> telStats =
|
||||
|
@ -350,6 +350,8 @@ XRE_InitChildProcess(int aArgc,
|
||||
// NB: This must be called before profiler_init
|
||||
NS_LogInit();
|
||||
|
||||
mozilla::LogModule::Init();
|
||||
|
||||
char aLocal;
|
||||
profiler_init(&aLocal);
|
||||
|
||||
|
100
xpcom/base/Logging.cpp
Normal file
100
xpcom/base/Logging.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
|
||||
// NB: Initial amount determined by auditing the codebase for the total amount
|
||||
// of unique module names and padding up to the next power of 2.
|
||||
const uint32_t kInitialModuleCount = 256;
|
||||
|
||||
namespace mozilla {
|
||||
/**
|
||||
* Safely converts an integer into a valid LogLevel.
|
||||
*/
|
||||
LogLevel
|
||||
Clamp(int32_t aLevel)
|
||||
{
|
||||
aLevel = std::min(aLevel, static_cast<int32_t>(LogLevel::Verbose));
|
||||
aLevel = std::max(aLevel, static_cast<int32_t>(LogLevel::Disabled));
|
||||
return static_cast<LogLevel>(aLevel);
|
||||
}
|
||||
|
||||
class LogModuleManager
|
||||
{
|
||||
public:
|
||||
LogModuleManager()
|
||||
: mModulesLock("logmodules")
|
||||
, mModules(kInitialModuleCount)
|
||||
{
|
||||
}
|
||||
|
||||
~LogModuleManager()
|
||||
{
|
||||
// NB: mModules owns all of the log modules, they will get destroyed by
|
||||
// its destructor.
|
||||
}
|
||||
|
||||
LogModule* CreateOrGetModule(const char* aName)
|
||||
{
|
||||
OffTheBooksMutexAutoLock guard(mModulesLock);
|
||||
LogModule* module = nullptr;
|
||||
if (!mModules.Get(aName, &module)) {
|
||||
// Create the PRLogModule, this will read any env vars that set the log
|
||||
// level ahead of time. The module is held internally by NSPR, so it's
|
||||
// okay to drop the pointer when leaving this scope.
|
||||
PRLogModuleInfo* prModule = PR_NewLogModule(aName);
|
||||
|
||||
// NSPR does not impose a restriction on the values that log levels can
|
||||
// be. LogModule uses the LogLevel enum class so we must clamp the value
|
||||
// to a max of Verbose.
|
||||
LogLevel logLevel = Clamp(prModule->level);
|
||||
module = new LogModule(logLevel);
|
||||
mModules.Put(aName, module);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
private:
|
||||
OffTheBooksMutex mModulesLock;
|
||||
nsClassHashtable<nsCharPtrHashKey, LogModule> mModules;
|
||||
};
|
||||
|
||||
StaticAutoPtr<LogModuleManager> sLogModuleManager;
|
||||
|
||||
LogModule*
|
||||
LogModule::Get(const char* aName)
|
||||
{
|
||||
// This is just a pass through to the LogModuleManager so
|
||||
// that the LogModuleManager implementation can be kept internal.
|
||||
MOZ_ASSERT(sLogModuleManager != nullptr);
|
||||
return sLogModuleManager->CreateOrGetModule(aName);
|
||||
}
|
||||
|
||||
void
|
||||
LogModule::Init()
|
||||
{
|
||||
// NB: This method is not threadsafe; it is expected to be called very early
|
||||
// in startup prior to any other threads being run.
|
||||
if (sLogModuleManager) {
|
||||
// Already initialized.
|
||||
return;
|
||||
}
|
||||
|
||||
// NB: We intentionally do not register for ClearOnShutdown as that happens
|
||||
// before all logging is complete. And, yes, that means we leak, but
|
||||
// we're doing that intentionally.
|
||||
sLogModuleManager = new LogModuleManager();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -10,6 +10,8 @@
|
||||
#include "prlog.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
// This file is a placeholder for a replacement to the NSPR logging framework
|
||||
// that is defined in prlog.h. Currently it is just a pass through, but as
|
||||
@ -43,6 +45,87 @@ enum class LogLevel {
|
||||
Verbose,
|
||||
};
|
||||
|
||||
class LogModule
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Retrieves the module with the given name. If it does not already exist
|
||||
* it will be created.
|
||||
*
|
||||
* @param aName The name of the module.
|
||||
* @return A log module for the given name. This may be shared.
|
||||
*/
|
||||
#if !defined(MOZILLA_XPCOMRT_API)
|
||||
static LogModule* Get(const char* aName);
|
||||
#else
|
||||
// For simplicity, libxpcomrt doesn't supoort logging.
|
||||
static LogModule* Get(const char* aName) { return nullptr; }
|
||||
#endif
|
||||
|
||||
static void Init();
|
||||
|
||||
/**
|
||||
* Indicates whether or not the given log level is enabled.
|
||||
*/
|
||||
bool ShouldLog(LogLevel aLevel) const { return mLevel >= aLevel; }
|
||||
|
||||
/**
|
||||
* Retrieves the log module's current level.
|
||||
*/
|
||||
LogLevel Level() const { return mLevel; }
|
||||
|
||||
private:
|
||||
friend class LogModuleManager;
|
||||
|
||||
explicit LogModule(LogLevel aLevel) : mLevel(aLevel) {}
|
||||
|
||||
LogModule(LogModule&) = delete;
|
||||
LogModule& operator=(const LogModule&) = delete;
|
||||
|
||||
Atomic<LogLevel, Relaxed> mLevel;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class that lazy loads the given log module. This is safe to use for
|
||||
* declaring static references to log modules and can be used as a replacement
|
||||
* for accessing a LogModule directly.
|
||||
*
|
||||
* Example usage:
|
||||
* static LazyLogModule sLayoutLog("layout");
|
||||
*
|
||||
* void Foo() {
|
||||
* MOZ_LOG(sLayoutLog, LogLevel::Verbose, ("Entering foo"));
|
||||
* }
|
||||
*/
|
||||
class LazyLogModule final
|
||||
{
|
||||
public:
|
||||
explicit MOZ_CONSTEXPR LazyLogModule(const char* aLogName)
|
||||
: mLogName(aLogName)
|
||||
, mLog(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
operator LogModule*()
|
||||
{
|
||||
// NB: The use of an atomic makes the reading and assignment of mLog
|
||||
// thread-safe. There is a small chance that mLog will be set more
|
||||
// than once, but that's okay as it will be set to the same LogModule
|
||||
// instance each time. Also note LogModule::Get is thread-safe.
|
||||
LogModule* tmp = mLog;
|
||||
if (MOZ_UNLIKELY(!tmp)) {
|
||||
tmp = LogModule::Get(mLogName);
|
||||
mLog = tmp;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* const mLogName;
|
||||
Atomic<LogModule*, ReleaseAcquire> mLog;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline bool log_test(const PRLogModuleInfo* module, LogLevel level) {
|
||||
@ -50,6 +133,11 @@ inline bool log_test(const PRLogModuleInfo* module, LogLevel level) {
|
||||
return module && module->level >= static_cast<int>(level);
|
||||
}
|
||||
|
||||
inline bool log_test(const LogModule* module, LogLevel level) {
|
||||
MOZ_ASSERT(level != LogLevel::Disabled);
|
||||
return module && module->ShouldLog(level);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mozilla
|
@ -83,6 +83,7 @@ EXPORTS.mozilla += [
|
||||
'HoldDropJSObjects.h',
|
||||
'JSObjectHolder.h',
|
||||
'LinuxUtils.h',
|
||||
'Logging.h',
|
||||
'nsMemoryInfoDumper.h',
|
||||
'OwningNonNull.h',
|
||||
'StaticMutex.h',
|
||||
@ -107,6 +108,7 @@ UNIFIED_SOURCES += [
|
||||
'ErrorNames.cpp',
|
||||
'HoldDropJSObjects.cpp',
|
||||
'JSObjectHolder.cpp',
|
||||
'Logging.cpp',
|
||||
'nsConsoleMessage.cpp',
|
||||
'nsConsoleService.cpp',
|
||||
'nsCycleCollector.cpp',
|
||||
|
@ -498,6 +498,8 @@ NS_InitXPCOM2(nsIServiceManager** aResult,
|
||||
|
||||
NS_LogInit();
|
||||
|
||||
mozilla::LogModule::Init();
|
||||
|
||||
JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation);
|
||||
|
||||
char aLocal;
|
||||
|
@ -75,7 +75,6 @@ EXPORTS.mozilla += [
|
||||
'FileUtils.h',
|
||||
'GenericFactory.h',
|
||||
'IntentionalCrash.h',
|
||||
'Logging.h',
|
||||
'Monitor.h',
|
||||
'Mutex.h',
|
||||
'Observer.h',
|
||||
|
Loading…
Reference in New Issue
Block a user