// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Threading;
namespace MessagePack
{
///
/// Special behavior for running on the mono runtime.
///
internal struct MonoProtection
{
///
/// Gets a value indicating whether the mono runtime is executing this code.
///
internal static bool IsRunningOnMono => Type.GetType("Mono.Runtime") != null;
///
/// A lock that we enter on mono when generating dynamic types.
///
private static readonly object RefEmitLock = new object();
///
/// The method to call within the expression of a using statement whose block surrounds all Ref.Emit code.
///
/// The value to be disposed of to exit the Ref.Emit lock.
///
/// This is a no-op except when running on Mono.
/// Mono's implementation of Ref.Emit is not thread-safe so we have to lock around all use of it
/// when using that runtime.
///
internal static MonoProtectionDisposal EnterRefEmitLock() => IsRunningOnMono ? new MonoProtectionDisposal(RefEmitLock) : default;
}
internal struct MonoProtectionDisposal : IDisposable
{
private readonly object lockObject;
internal MonoProtectionDisposal(object lockObject)
{
this.lockObject = lockObject;
Monitor.Enter(lockObject);
}
public void Dispose()
{
if (this.lockObject is object)
{
Monitor.Exit(this.lockObject);
}
}
}
}