<commit_before>// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Platform;

namespace Avalonia.Shared.PlatformSupport
{
    internal partial class StandardRuntimePlatform : IRuntimePlatform
    {
        public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
        public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
        public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
        {
            return new Timer(_ => tick(), null, interval, interval);
        }

        public string GetStackTrace() => Environment.StackTrace;

        public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(this, size);
        
        class UnmanagedBlob : IUnmanagedBlob
        {
            private readonly StandardRuntimePlatform _plat;
#if DEBUG
            private static readonly List<string> Backtraces = new List<string>();
            private static Thread GCThread;
            private readonly string _backtrace;


            class GCThreadDetector
            {
                ~GCThreadDetector()
                {
                    GCThread = Thread.CurrentThread;
                }
            }

            [MethodImpl(MethodImplOptions.NoInlining)]
            static void Spawn() => new GCThreadDetector();
            
            static UnmanagedBlob()
            {
                Spawn();
                GC.WaitForPendingFinalizers();
            }
            
#endif
            
            public UnmanagedBlob(StandardRuntimePlatform plat, int size)
            {
                _plat = plat;
                Address = plat.Alloc(size);
                GC.AddMemoryPressure(size);
                Size = size;
#if DEBUG
                _backtrace = Environment.StackTrace;
                Backtraces.Add(_backtrace);
#endif
            }

            void DoDispose()
            {
                if (!IsDisposed)
                {
#if DEBUG
                    Backtraces.Remove(_backtrace);
#endif
                    _plat.Free(Address, Size);
                    GC.RemoveMemoryPressure(Size);
                    IsDisposed = true;
                    Address = IntPtr.Zero;
                }
            }

            public void Dispose()
            {
#if DEBUG
                if (Thread.CurrentThread.ManagedThreadId == GCThread?.ManagedThreadId)
                {
                    Console.Error.WriteLine("Native blob disposal from finalizer thread\nBacktrace: "
                                            + Environment.StackTrace
                                            + "\n\nBlob created by " + _backtrace);
                }
#endif
                DoDispose();
                GC.SuppressFinalize(this);
            }

            ~UnmanagedBlob()
            {
#if DEBUG
                Console.Error.WriteLine("Undisposed native blob created by " + _backtrace);
#endif
                DoDispose();
            }<commit_msg>Set NativeBlob.Size to zero on dispose<commit_after>// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Platform;

namespace Avalonia.Shared.PlatformSupport
{
    internal partial class StandardRuntimePlatform : IRuntimePlatform
    {
        public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
        public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
        public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
        {
            return new Timer(_ => tick(), null, interval, interval);
        }

        public string GetStackTrace() => Environment.StackTrace;

        public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(this, size);
        
        class UnmanagedBlob : IUnmanagedBlob
        {
            private readonly StandardRuntimePlatform _plat;
#if DEBUG
            private static readonly List<string> Backtraces = new List<string>();
            private static Thread GCThread;
            private readonly string _backtrace;


            class GCThreadDetector
            {
                ~GCThreadDetector()
                {
                    GCThread = Thread.CurrentThread;
                }
            }

            [MethodImpl(MethodImplOptions.NoInlining)]
            static void Spawn() => new GCThreadDetector();
            
            static UnmanagedBlob()
            {
                Spawn();
                GC.WaitForPendingFinalizers();
            }
            
#endif
            
            public UnmanagedBlob(StandardRuntimePlatform plat, int size)
            {
                _plat = plat;
                Address = plat.Alloc(size);
                GC.AddMemoryPressure(size);
                Size = size;
#if DEBUG
                _backtrace = Environment.StackTrace;
                Backtraces.Add(_backtrace);
#endif
            }

            void DoDispose()
            {
                if (!IsDisposed)
                {
#if DEBUG
                    Backtraces.Remove(_backtrace);
#endif
                    _plat.Free(Address, Size);
                    GC.RemoveMemoryPressure(Size);
                    IsDisposed = true;
                    Address = IntPtr.Zero;
                    Size = 0;
                }
            }

            public void Dispose()
            {
#if DEBUG
                if (Thread.CurrentThread.ManagedThreadId == GCThread?.ManagedThreadId)
                {
                    Console.Error.WriteLine("Native blob disposal from finalizer thread\nBacktrace: "
                                            + Environment.StackTrace
                                            + "\n\nBlob created by " + _backtrace);
                }
#endif
                DoDispose();
                GC.SuppressFinalize(this);
            }

            ~UnmanagedBlob()
            {
#if DEBUG
                Console.Error.WriteLine("Undisposed native blob created by " + _backtrace);
#endif
                DoDispose();
            }
{'fraction_non_alphanumeric': 0.07602339181286549, 'fraction_numerical': 0.000149947518368571, 'mean_word_length': 1.5614439324116745, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7482894', 'n_tokens_mistral': 1586, 'n_tokens_neox': 1507, 'n_words': 385}