//****************************************

        private static AsyncHandleWaiter CreateWaiter(WaitHandle waitObject, TimeSpan timeout, CancellationToken token = default)
        {
            if (waitObject == null)
            {
                throw new ArgumentNullException(nameof(waitObject));
            }

            if (timeout == TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), "Timeout must be infinite, or positive");
            }

            // We want to guarantee that only one AsyncHandle is associated per WaitHandle.
            // This AsyncHandle will persist for the life of the WaitHandle, until it is disposed
            var Handle = _AsyncHandles.GetValue(waitObject, AsyncHandle.Create);

            // GetValue may call GetOrCreate multiple times, so we only register the handle once we have the final result
            Handle.Register();

            // To allow each async wait to be cancellable, we need to track them independently
            var Waiter = AsyncHandleWaiter.GetOrCreate(Handle);

            Waiter.ApplyCancellation(timeout, token);

            return(Waiter);
        }
            //****************************************

            internal static AsyncHandleWaiter GetOrCreate(AsyncHandle handle)
            {
                if (!Instances.TryTake(out var Instance))
                {
                    Instance = new AsyncHandleWaiter();
                }

                Instance.Initialise(handle);

                return(Instance);
            }
 internal bool Detach(AsyncHandleWaiter waiter) => _Waiters.Erase(waiter);
 internal void Attach(AsyncHandleWaiter waiter) => _Waiters.Enqueue(waiter);