|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.Internal.Log;
/// <summary>
/// log message that can generate string lazily
/// </summary>
internal abstract class LogMessage
{
public LogLevel LogLevel { get; protected set; } = LogLevel.Debug;
public static LogMessage Create(string message, LogLevel logLevel)
=> StaticLogMessage.Construct(message, logLevel);
public static LogMessage Create(Func<string> messageGetter, LogLevel logLevel)
=> LazyLogMessage.Construct(messageGetter, logLevel);
public static LogMessage Create<TArg>(Func<TArg, string> messageGetter, TArg arg, LogLevel logLevel)
=> LazyLogMessage<TArg>.Construct(messageGetter, arg, logLevel);
public static LogMessage Create<TArg0, TArg1>(Func<TArg0, TArg1, string> messageGetter, TArg0 arg0, TArg1 arg1, LogLevel logLevel)
=> LazyLogMessage<TArg0, TArg1>.Construct(messageGetter, arg0, arg1, logLevel);
public static LogMessage Create<TArg0, TArg1, TArg2>(Func<TArg0, TArg1, TArg2, string> messageGetter, TArg0 arg0, TArg1 arg1, TArg2 arg2, LogLevel logLevel)
=> LazyLogMessage<TArg0, TArg1, TArg2>.Construct(messageGetter, arg0, arg1, arg2, logLevel);
public static LogMessage Create<TArg0, TArg1, TArg2, TArg3>(Func<TArg0, TArg1, TArg2, TArg3, string> messageGetter, TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, LogLevel logLevel)
=> LazyLogMessage<TArg0, TArg1, TArg2, TArg3>.Construct(messageGetter, arg0, arg1, arg2, arg3, logLevel);
// message will be either initially set or lazily set by caller
private string? _message;
protected abstract string CreateMessage();
/// <summary>
/// Logger will call this to return LogMessage to its pool
/// </summary>
protected abstract void FreeCore();
public string GetMessage()
{
_message ??= CreateMessage();
return _message;
}
public void Free()
{
_message = null;
FreeCore();
}
private sealed class StaticLogMessage : LogMessage
{
private static readonly ObjectPool<StaticLogMessage> s_pool = SharedPools.Default<StaticLogMessage>();
public static LogMessage Construct(string message, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._message = message;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _message!;
protected override void FreeCore()
{
if (_message == null)
{
return;
}
_message = null;
s_pool.Free(this);
}
}
private sealed class LazyLogMessage : LogMessage
{
private static readonly ObjectPool<LazyLogMessage> s_pool = SharedPools.Default<LazyLogMessage>();
private Func<string>? _messageGetter;
public static LogMessage Construct(Func<string> messageGetter, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._messageGetter = messageGetter;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _messageGetter!();
protected override void FreeCore()
{
if (_messageGetter == null)
{
return;
}
_messageGetter = null;
s_pool.Free(this);
}
}
private sealed class LazyLogMessage<TArg0> : LogMessage
{
private static readonly ObjectPool<LazyLogMessage<TArg0>> s_pool = SharedPools.Default<LazyLogMessage<TArg0>>();
private Func<TArg0, string>? _messageGetter;
private TArg0? _arg;
public static LogMessage Construct(Func<TArg0, string> messageGetter, TArg0 arg, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._messageGetter = messageGetter;
logMessage._arg = arg;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _messageGetter!(_arg!);
protected override void FreeCore()
{
if (_messageGetter == null)
{
return;
}
_messageGetter = null;
_arg = default;
s_pool.Free(this);
}
}
private sealed class LazyLogMessage<TArg0, TArg1> : LogMessage
{
private static readonly ObjectPool<LazyLogMessage<TArg0, TArg1>> s_pool = SharedPools.Default<LazyLogMessage<TArg0, TArg1>>();
private Func<TArg0, TArg1, string>? _messageGetter;
private TArg0? _arg0;
private TArg1? _arg1;
internal static LogMessage Construct(Func<TArg0, TArg1, string> messageGetter, TArg0 arg0, TArg1 arg1, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._messageGetter = messageGetter;
logMessage._arg0 = arg0;
logMessage._arg1 = arg1;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _messageGetter!(_arg0!, _arg1!);
protected override void FreeCore()
{
if (_messageGetter == null)
{
return;
}
_messageGetter = null;
_arg0 = default;
_arg1 = default;
s_pool.Free(this);
}
}
private sealed class LazyLogMessage<TArg0, TArg1, TArg2> : LogMessage
{
private static readonly ObjectPool<LazyLogMessage<TArg0, TArg1, TArg2>> s_pool = SharedPools.Default<LazyLogMessage<TArg0, TArg1, TArg2>>();
private Func<TArg0, TArg1, TArg2, string>? _messageGetter;
private TArg0? _arg0;
private TArg1? _arg1;
private TArg2? _arg2;
public static LogMessage Construct(Func<TArg0, TArg1, TArg2, string> messageGetter, TArg0 arg0, TArg1 arg1, TArg2 arg2, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._messageGetter = messageGetter;
logMessage._arg0 = arg0;
logMessage._arg1 = arg1;
logMessage._arg2 = arg2;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _messageGetter!(_arg0!, _arg1!, _arg2!);
protected override void FreeCore()
{
if (_messageGetter == null)
{
return;
}
_messageGetter = null;
_arg0 = default;
_arg1 = default;
_arg2 = default;
s_pool.Free(this);
}
}
private sealed class LazyLogMessage<TArg0, TArg1, TArg2, TArg3> : LogMessage
{
private static readonly ObjectPool<LazyLogMessage<TArg0, TArg1, TArg2, TArg3>> s_pool = SharedPools.Default<LazyLogMessage<TArg0, TArg1, TArg2, TArg3>>();
private Func<TArg0, TArg1, TArg2, TArg3, string>? _messageGetter;
private TArg0? _arg0;
private TArg1? _arg1;
private TArg2? _arg2;
private TArg3? _arg3;
public static LogMessage Construct(Func<TArg0, TArg1, TArg2, TArg3, string> messageGetter, TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, LogLevel logLevel)
{
var logMessage = s_pool.Allocate();
logMessage._messageGetter = messageGetter;
logMessage._arg0 = arg0;
logMessage._arg1 = arg1;
logMessage._arg2 = arg2;
logMessage._arg3 = arg3;
logMessage.LogLevel = logLevel;
return logMessage;
}
protected override string CreateMessage()
=> _messageGetter!(_arg0!, _arg1!, _arg2!, _arg3!);
protected override void FreeCore()
{
if (_messageGetter == null)
{
return;
}
_messageGetter = null;
_arg0 = default;
_arg1 = default;
_arg2 = default;
_arg3 = default;
s_pool.Free(this);
}
}
}
|