public static CompletionSource Create(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped?preallocatedOverlapped,
                                       int numBufferedBytesRead, ReadOnlyMemory <byte> memory)
 {
     // If the memory passed in is the strategy's internal buffer, we can use the base FileStreamCompletionSource,
     // which has a PreAllocatedOverlapped with the memory already pinned.  Otherwise, we use the derived
     // MemoryFileStreamCompletionSource, which Retains the memory, which will result in less pinning in the case
     // where the underlying memory is backed by pre-pinned buffers.
     return(preallocatedOverlapped != null && MemoryMarshal.TryGetArray(memory, out ArraySegment <byte> buffer) &&
            preallocatedOverlapped.IsUserObject(buffer.Array) // preallocatedOverlapped is allocated when BufferedStream|Net5CompatFileStreamStrategy allocates the buffer
         ? new CompletionSource(strategy, preallocatedOverlapped, numBufferedBytesRead, buffer.Array)
         : new MemoryFileStreamCompletionSource(strategy, numBufferedBytesRead, memory));
 }
            private long _result;                  // Using long since this needs to be used in Interlocked APIs

            // Using RunContinuationsAsynchronously for compat reasons (old API used Task.Factory.StartNew for continuations)
            internal CompletionSource(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped?preallocatedOverlapped,
                                      int numBufferedBytes, byte[]?bytes) : base(TaskCreationOptions.RunContinuationsAsynchronously)
            {
                _numBufferedBytes = numBufferedBytes;
                _strategy         = strategy;
                _result           = TaskSourceCodes.NoResult;

                // The _preallocatedOverlapped is null if the internal buffer was never created, so we check for
                // a non-null bytes before using the stream's _preallocatedOverlapped
                _overlapped = bytes != null && strategy.CompareExchangeCurrentOverlappedOwner(this, null) == null ?
                              strategy._fileHandle.ThreadPoolBinding !.AllocateNativeOverlapped(preallocatedOverlapped !) : // allocated when buffer was created, and buffer is non-null
                              strategy._fileHandle.ThreadPoolBinding !.AllocateNativeOverlapped(s_ioCallback, this, bytes);
                Debug.Assert(_overlapped != null, "AllocateNativeOverlapped returned null");
            }
            // When doing IO asynchronously (i.e. _isAsync==true), this callback is
            // called by a free thread in the threadpool when the IO operation
            // completes.
            internal static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
            {
                // Extract the completion source from the overlapped.  The state in the overlapped
                // will either be a FileStreamStrategy (in the case where the preallocated overlapped was used),
                // in which case the operation being completed is its _currentOverlappedOwner, or it'll
                // be directly the FileStreamCompletionSource that's completing (in the case where the preallocated
                // overlapped was already in use by another operation).
                object?state = ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);

                Debug.Assert(state is Net5CompatFileStreamStrategy || state is CompletionSource);
                CompletionSource completionSource = state switch
                {
                    Net5CompatFileStreamStrategy strategy => strategy._currentOverlappedOwner !, // must be owned
                                 _ => (CompletionSource)state
                };

                Debug.Assert(completionSource != null);
                Debug.Assert(completionSource._overlapped == pOverlapped, "Overlaps don't match");

                // Handle reading from & writing to closed pipes.  While I'm not sure
                // this is entirely necessary anymore, maybe it's possible for
                // an async read on a pipe to be issued and then the pipe is closed,
                // returning this error.  This may very well be necessary.
                ulong packedResult;

                if (errorCode != 0 && errorCode != Interop.Errors.ERROR_BROKEN_PIPE && errorCode != Interop.Errors.ERROR_NO_DATA)
                {
                    packedResult = ((ulong)TaskSourceCodes.ResultError | errorCode);
                }
                else
                {
                    packedResult = ((ulong)TaskSourceCodes.ResultSuccess | numBytes);
                }

                // Stow the result so that other threads can observe it
                // And, if no other thread is registering cancellation, continue
                if (TaskSourceCodes.NoResult == Interlocked.Exchange(ref completionSource._result, (long)packedResult))
                {
                    // Successfully set the state, attempt to take back the callback
                    if (Interlocked.Exchange(ref completionSource._result, TaskSourceCodes.CompletedCallback) != TaskSourceCodes.NoResult)
                    {
                        // Successfully got the callback, finish the callback
                        completionSource.CompleteCallback(packedResult);
                    }
                    // else: Some other thread stole the result, so now it is responsible to finish the callback
                }
                // else: Some other thread is registering a cancellation, so it *must* finish the callback
            }
            private MemoryHandle _handle; // mutable struct; do not make this readonly

            internal MemoryFileStreamCompletionSource(Net5CompatFileStreamStrategy strategy, int numBufferedBytes, ReadOnlyMemory <byte> memory)
                : base(strategy, null, numBufferedBytes, null) // this type handles the pinning, so null is passed for bytes
            {
                _handle = memory.Pin();
            }