<commit_before>﻿using System;
using System.Collections.Generic;
using System.Threading;
using Theraot.Threading.Needles;

namespace Theraot.Core.Threading
{
    public class Timeout : IDisposable, IPromise
    {
        private static readonly HashSet<Timeout> _root;

        private readonly int _hashcode;
        private Action _callback;
        private bool _completed;
        private bool _rooted;
        private Timer _wrapped;

        static Timeout()
        {
            _root = new HashSet<Timeout>();
        }

        public Timeout(Action callback, long dueTime)
        {
            if (callback == null)
            {
                throw new NullReferenceException("callback");
            }
            _callback = callback;
            _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite);
            _hashcode = unchecked((int)DateTime.Now.Ticks);
        }

        public Timeout(Action callback, long dueTime, CancellationToken token)
        {
            if (callback == null)
            {
                throw new NullReferenceException("callback");
            }
            if (token.IsCancellationRequested)
            {
                _callback = null;
                _wrapped = null;
            }
            else
            {
                _callback = callback;
                _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite);
                token.Register(Dispose);
            }
            _hashcode = unchecked((int)DateTime.Now.Ticks);
        }

        public Timeout(Action callback, TimeSpan dueTime)
            : this(callback, (long)dueTime.TotalMilliseconds)
        {
            // Empty
        }

        public Timeout(Action callback, TimeSpan dueTime, CancellationToken token)
            : this(callback, (long)dueTime.TotalMilliseconds, token)
        {
            // Empty
        }

        ~Timeout()
        {
            Dispose();
        }

        Exception IPromise.Exception
        {
            get
            {
                return null;
            }
        }

        bool IPromise.IsFaulted
        {
            get
            {
                return false;
            }
        }

        public bool IsCanceled
        {
            get
            {
                return _wrapped == null;
            }
        }

        public bool IsCompleted
        {
            get
            {
                return _completed;
            }
        }

        public bool Rooted
        {
            get
            {
                return _rooted;
            }
            set
            {
                if (value == _rooted)
                {
                    return;
                }
                if (value)
                {
                    _root.Add(this);
                }
                else
                {
                    _root.Remove(this);
                }
                _rooted = value;
            }
        }

        public void Change(long dueTime)
        {
            _wrapped.Change(dueTime, System.Threading.Timeout.Infinite);
        }

        public void Change(TimeSpan dueTime)
        {
            Change((long)dueTime.TotalMilliseconds);
        }

        public void Dispose()
        {
            var wrapped = Interlocked.Exchange(ref _wrapped, null);
            if (wrapped != null)
            {
                wrapped.Dispose();
            }
            _callback = null;
            _root.Remove(this);
            GC.SuppressFinalize(this);
        }

        public override bool Equals(object obj)
        {
            if (obj is Timeout)
            {
                return ReferenceEquals(this, obj);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return _hashcode;
        }

        private void Callback(object state)
        {
            GC.KeepAlive(state);
            _callback.Invoke();
            _completed = true;
            Dispose();
        }
    }
}<commit_msg>Timeout no longer disposable<commit_after>﻿using System;
using System.Collections.Generic;
using System.Threading;
using Theraot.Threading.Needles;

namespace Theraot.Core.Threading
{
    public class Timeout : IPromise
    {
        private static readonly HashSet<Timeout> _root;

        private readonly int _hashcode;
        private Action _callback;
        private bool _completed;
        private bool _rooted;
        private Timer _wrapped;

        static Timeout()
        {
            _root = new HashSet<Timeout>();
        }

        public Timeout(Action callback, long dueTime)
        {
            if (callback == null)
            {
                throw new NullReferenceException("callback");
            }
            _callback = callback;
            _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite);
            _hashcode = unchecked((int)DateTime.Now.Ticks);
        }

        public Timeout(Action callback, long dueTime, CancellationToken token)
        {
            if (callback == null)
            {
                throw new NullReferenceException("callback");
            }
            if (token.IsCancellationRequested)
            {
                _callback = null;
                _wrapped = null;
            }
            else
            {
                _callback = callback;
                _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite);
                token.Register(Cancel);
            }
            _hashcode = unchecked((int)DateTime.Now.Ticks);
        }

        public Timeout(Action callback, TimeSpan dueTime)
            : this(callback, (long)dueTime.TotalMilliseconds)
        {
            // Empty
        }

        public Timeout(Action callback, TimeSpan dueTime, CancellationToken token)
            : this(callback, (long)dueTime.TotalMilliseconds, token)
        {
            // Empty
        }

        ~Timeout()
        {
            Cancel();
        }

        Exception IPromise.Exception
        {
            get
            {
                return null;
            }
        }

        bool IPromise.IsFaulted
        {
            get
            {
                return false;
            }
        }

        public bool IsCanceled
        {
            get
            {
                return _wrapped == null;
            }
        }

        public bool IsCompleted
        {
            get
            {
                return _completed;
            }
        }

        public bool Rooted
        {
            get
            {
                return _rooted;
            }
            set
            {
                if (value == _rooted)
                {
                    return;
                }
                if (value)
                {
                    _root.Add(this);
                }
                else
                {
                    _root.Remove(this);
                }
                _rooted = value;
            }
        }

        public void Change(long dueTime)
        {
            _wrapped.Change(dueTime, System.Threading.Timeout.Infinite);
        }

        public void Change(TimeSpan dueTime)
        {
            Change((long)dueTime.TotalMilliseconds);
        }

        public void Cancel()
        {
            var wrapped = Interlocked.Exchange(ref _wrapped, null);
            if (wrapped != null)
            {
                wrapped.Dispose();
            }
            _callback = null;
            _root.Remove(this);
            GC.SuppressFinalize(this);
        }

        public override bool Equals(object obj)
        {
            if (obj is Timeout)
            {
                return ReferenceEquals(this, obj);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return _hashcode;
        }

        private void Callback(object state)
        {
            GC.KeepAlive(state);
            _callback.Invoke();
            _completed = true;
            Cancel();
        }
    }
}
{'fraction_non_alphanumeric': 0.07487745098039215, 'fraction_numerical': 0.0, 'mean_word_length': 1.0718456461030719, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5915987', 'n_tokens_mistral': 2045, 'n_tokens_neox': 1963, 'n_words': 424}