// 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); } } } }