Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Net5CompatFileStreamStrategy.cs
Go to the documentation of this file.
6
8
10{
12 {
13 internal unsafe static readonly IOCompletionCallback s_ioCallback = IOCallback;
14
15 private static Action<object> s_cancelCallback;
16
18
19 private readonly int _numBufferedBytes;
20
22
24
25 private long _result;
26
28
29 internal unsafe CompletionSource(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped preallocatedOverlapped, int numBufferedBytes, byte[] bytes)
31 {
32 _numBufferedBytes = numBufferedBytes;
33 _strategy = strategy;
34 _result = 0L;
36 }
37
38 public void SetCompletedSynchronously(int numBytes)
39 {
42 }
43
45 {
46 if (_overlapped != null)
47 {
48 Action<object> callback = Cancel;
49 long num = Interlocked.CompareExchange(ref _result, 17179869184L, 0L);
50 switch (num)
51 {
52 case 0L:
53 _cancellationRegistration = cancellationToken.UnsafeRegister(callback, this);
54 num = Interlocked.Exchange(ref _result, 0L);
55 break;
56 default:
57 num = Interlocked.Exchange(ref _result, 0L);
58 break;
59 case 34359738368L:
60 break;
61 }
62 if (num != 0L && num != 34359738368L && num != 17179869184L)
63 {
64 CompleteCallback((ulong)num);
65 }
66 }
67 }
68
79
80 internal unsafe static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped)
81 {
82 object nativeOverlappedState = ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);
83 CompletionSource completionSource = ((!(nativeOverlappedState is Net5CompatFileStreamStrategy net5CompatFileStreamStrategy)) ? ((CompletionSource)nativeOverlappedState) : net5CompatFileStreamStrategy._currentOverlappedOwner);
84 CompletionSource completionSource2 = completionSource;
85 ulong num = ((errorCode == 0 || errorCode == 109 || errorCode == 232) ? (0x100000000uL | numBytes) : (0x200000000uL | errorCode));
86 if (Interlocked.Exchange(ref completionSource2._result, (long)num) == 0L && Interlocked.Exchange(ref completionSource2._result, 34359738368L) != 0L)
87 {
88 completionSource2.CompleteCallback(num);
89 }
90 }
91
92 private void CompleteCallback(ulong packedResult)
93 {
96 long num = (long)packedResult & -4294967296L;
97 if (num == 8589934592L)
98 {
99 int num2 = (int)(packedResult & 0xFFFFFFFFu);
100 if (num2 == 995)
101 {
102 TrySetCanceled(token.IsCancellationRequested ? token : new CancellationToken(canceled: true));
103 return;
104 }
105 Exception exceptionForWin32Error = Win32Marshal.GetExceptionForWin32Error(num2);
106 exceptionForWin32Error.SetCurrentStackTrace();
107 TrySetException(exceptionForWin32Error);
108 }
109 else
110 {
111 TrySetResult((int)(packedResult & 0xFFFFFFFFu) + _numBufferedBytes);
112 }
113 }
114
115 private unsafe static void Cancel(object state)
116 {
117 CompletionSource completionSource = (CompletionSource)state;
118 if (!completionSource._strategy._fileHandle.IsInvalid && !Interop.Kernel32.CancelIoEx(completionSource._strategy._fileHandle, completionSource._overlapped))
119 {
120 int lastPInvokeError = Marshal.GetLastPInvokeError();
121 if (lastPInvokeError != 1168)
122 {
123 throw Win32Marshal.GetExceptionForWin32Error(lastPInvokeError);
124 }
125 }
126 }
127
128 public static CompletionSource Create(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped preallocatedOverlapped, int numBufferedBytesRead, ReadOnlyMemory<byte> memory)
129 {
130 if (preallocatedOverlapped == null || !MemoryMarshal.TryGetArray(memory, out var segment) || !preallocatedOverlapped.IsUserObject(segment.Array))
131 {
132 return new MemoryFileStreamCompletionSource(strategy, numBufferedBytesRead, memory);
133 }
134 return new CompletionSource(strategy, preallocatedOverlapped, numBufferedBytesRead, segment.Array);
135 }
136 }
137
139 {
141
143 : base(strategy, null, numBufferedBytes, null)
144 {
145 _handle = memory.Pin();
146 }
147
148 internal override void ReleaseNativeResource()
149 {
151 base.ReleaseNativeResource();
152 }
153 }
154
155 private byte[] _buffer;
156
157 private readonly int _bufferLength;
158
159 private readonly SafeFileHandle _fileHandle;
160
161 private readonly FileAccess _access;
162
163 private int _readPos;
164
165 private int _readLength;
166
167 private int _writePos;
168
169 private readonly bool _useAsyncIO;
170
172
173 private long _filePosition;
174
175 private bool _exposedHandle;
176
177 private long _appendStart;
178
180
182
184
185 public override bool CanRead
186 {
187 get
188 {
190 {
191 return (_access & FileAccess.Read) != 0;
192 }
193 return false;
194 }
195 }
196
197 public override bool CanWrite
198 {
199 get
200 {
202 {
203 return (_access & FileAccess.Write) != 0;
204 }
205 return false;
206 }
207 }
208
210 {
211 get
212 {
213 Flush();
214 _exposedHandle = true;
215 return _fileHandle;
216 }
217 }
218
219 internal override string Name => _fileHandle.Path ?? SR.IO_UnknownFileName;
220
221 internal override bool IsAsync => _useAsyncIO;
222
223 public override long Position
224 {
225 get
226 {
229 }
230 set
231 {
232 Seek(value, SeekOrigin.Begin);
233 }
234 }
235
236 internal override bool IsClosed => _fileHandle.IsClosed;
237
239
240 public override bool CanSeek => _fileHandle.CanSeek;
241
242 public override long Length
243 {
244 get
245 {
247 if (_writePos > 0 && _filePosition + _writePos > num)
248 {
249 num = _writePos + _filePosition;
250 }
251 return num;
252 }
253 }
254
255 internal Net5CompatFileStreamStrategy(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
256 {
257 _exposedHandle = true;
258 _bufferLength = bufferSize;
259 InitFromHandle(handle, access, isAsync);
260 _access = access;
261 _useAsyncIO = isAsync;
263 }
264
265 internal Net5CompatFileStreamStrategy(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize)
266 {
267 string fullPath = Path.GetFullPath(path);
268 _access = access;
269 _bufferLength = bufferSize;
270 if ((options & FileOptions.Asynchronous) != 0)
271 {
272 _useAsyncIO = true;
273 }
274 _fileHandle = SafeFileHandle.Open(fullPath, mode, access, share, options, preallocationSize);
275 try
276 {
277 Init(mode, path, options);
278 }
279 catch
280 {
282 _fileHandle = null;
283 throw;
284 }
285 }
286
288 {
289 Dispose(disposing: false);
290 }
291
292 internal override void DisposeInternal(bool disposing)
293 {
294 Dispose(disposing);
295 }
296
298 {
299 try
300 {
302 }
303 catch (Exception exception)
304 {
306 }
307 return Task.CompletedTask;
308 }
309
310 public override int Read(byte[] buffer, int offset, int count)
311 {
312 if (!_useAsyncIO)
313 {
314 return ReadSpan(new Span<byte>(buffer, offset, count));
315 }
317 }
318
319 public override int Read(Span<byte> buffer)
320 {
321 if (!_useAsyncIO)
322 {
324 {
326 }
327 return ReadSpan(buffer);
328 }
329 return base.Read(buffer);
330 }
331
333 {
334 if (!_useAsyncIO)
335 {
336 return BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
337 }
339 }
340
342 {
343 if (!_useAsyncIO)
344 {
345 if (!MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)buffer, out ArraySegment<byte> segment))
346 {
347 return base.ReadAsync(buffer, cancellationToken);
348 }
349 return new ValueTask<int>(BeginReadInternal(segment.Array, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false));
350 }
351 int synchronousResult;
352 Task<int> task = ReadAsyncInternal(buffer, cancellationToken, out synchronousResult);
353 if (task == null)
354 {
355 return new ValueTask<int>(synchronousResult);
356 }
357 return new ValueTask<int>(task);
358 }
359
361 {
362 int synchronousResult;
364 if (task == null)
365 {
367 if (task == null || task.Result != synchronousResult)
368 {
369 task = (_lastSynchronouslyCompletedTask = Task.FromResult(synchronousResult));
370 }
371 }
372 return task;
373 }
374
375 public override void Write(byte[] buffer, int offset, int count)
376 {
377 if (_useAsyncIO)
378 {
380 }
381 else
382 {
384 }
385 }
386
387 public override void Write(ReadOnlySpan<byte> buffer)
388 {
389 if (!_useAsyncIO)
390 {
392 {
394 }
396 }
397 else
398 {
399 base.Write(buffer);
400 }
401 }
402
404 {
405 if (!_useAsyncIO)
406 {
407 return BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
408 }
410 }
411
413 {
414 if (!_useAsyncIO)
415 {
416 if (!MemoryMarshal.TryGetArray(buffer, out var segment))
417 {
418 return base.WriteAsync(buffer, cancellationToken);
419 }
420 return new ValueTask(BeginWriteInternal(segment.Array, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false));
421 }
423 }
424
425 public override void Flush()
426 {
427 Flush(flushToDisk: false);
428 }
429
430 internal override void Flush(bool flushToDisk)
431 {
433 if (flushToDisk && CanWrite)
434 {
436 }
437 }
438
440 {
441 if (!_exposedHandle || !CanSeek)
442 {
443 return;
444 }
445 long filePosition = _filePosition;
446 long num = SeekCore(_fileHandle, 0L, SeekOrigin.Current);
447 if (filePosition != num)
448 {
449 _readPos = (_readLength = 0);
450 if (_writePos > 0)
451 {
452 _writePos = 0;
454 }
455 }
456 }
457
469
470 private long SeekCore(SafeFileHandle fileHandle, long offset, SeekOrigin origin, bool closeInvalidHandle = false)
471 {
472 return _filePosition = FileStreamHelpers.Seek(fileHandle, offset, origin, closeInvalidHandle);
473 }
474
475 private byte[] GetBuffer()
476 {
477 if (_buffer == null)
478 {
479 _buffer = new byte[_bufferLength];
481 }
482 return _buffer;
483 }
484
485 private void FlushInternalBuffer()
486 {
487 if (_writePos > 0)
488 {
490 }
491 else if (_readPos < _readLength && CanSeek)
492 {
494 }
495 }
496
497 private void FlushReadBuffer()
498 {
499 int num = _readPos - _readLength;
500 if (num != 0)
501 {
502 SeekCore(_fileHandle, num, SeekOrigin.Current);
503 }
504 _readPos = (_readLength = 0);
505 }
506
507 public override int ReadByte()
508 {
510 byte[] buffer = GetBuffer();
511 if (_readPos == _readLength)
512 {
515 _readPos = 0;
516 if (_readLength == 0)
517 {
518 return -1;
519 }
520 }
521 return buffer[_readPos++];
522 }
523
524 public override void WriteByte(byte value)
525 {
528 {
530 }
532 }
533
534 private void PrepareForWriting()
535 {
537 {
539 }
540 if (_writePos == 0)
541 {
542 if (!CanWrite)
543 {
545 }
547 }
548 }
549
557
558 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
559 {
560 if (!_useAsyncIO)
561 {
562 return base.BeginRead(buffer, offset, count, callback, state);
563 }
565 }
566
567 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
568 {
569 if (!_useAsyncIO)
570 {
571 return base.BeginWrite(buffer, offset, count, callback, state);
572 }
574 }
575
576 public override int EndRead(IAsyncResult asyncResult)
577 {
578 if (!_useAsyncIO)
579 {
580 return base.EndRead(asyncResult);
581 }
582 return TaskToApm.End<int>(asyncResult);
583 }
584
585 public override void EndWrite(IAsyncResult asyncResult)
586 {
587 if (!_useAsyncIO)
588 {
589 base.EndWrite(asyncResult);
590 }
591 else
592 {
594 }
595 }
596
597 private void Init(FileMode mode, string originalPath, FileOptions options)
598 {
599 if (mode == FileMode.Append)
600 {
602 }
603 else
604 {
605 _appendStart = -1L;
606 }
607 }
608
609 private void InitFromHandle(SafeFileHandle handle, FileAccess access, bool useAsyncIO)
610 {
611 InitFromHandleImpl(handle, useAsyncIO);
612 }
613
614 private void InitFromHandleImpl(SafeFileHandle handle, bool useAsyncIO)
615 {
616 handle.EnsureThreadPoolBindingInitialized();
617 if (handle.CanSeek)
618 {
619 SeekCore(handle, 0L, SeekOrigin.Current);
620 }
621 else
622 {
623 _filePosition = 0L;
624 }
625 }
626
627 protected override void Dispose(bool disposing)
628 {
629 try
630 {
631 if (_fileHandle != null && !_fileHandle.IsClosed && _writePos > 0)
632 {
633 try
634 {
635 FlushWriteBuffer(!disposing);
636 return;
637 }
638 catch (Exception e) when (!disposing && FileStreamHelpers.IsIoRelatedException(e))
639 {
640 return;
641 }
642 }
643 }
644 finally
645 {
646 if (_fileHandle != null && !_fileHandle.IsClosed)
647 {
650 }
652 }
653 }
654
655 public override async ValueTask DisposeAsync()
656 {
657 try
658 {
659 if (_fileHandle != null && !_fileHandle.IsClosed && _writePos > 0)
660 {
661 await FlushAsync(default(CancellationToken)).ConfigureAwait(continueOnCapturedContext: false);
662 }
663 }
664 finally
665 {
666 if (_fileHandle != null && !_fileHandle.IsClosed)
667 {
670 }
672 GC.SuppressFinalize(this);
673 }
674 }
675
687
689 {
691 }
692
693 private void FlushWriteBuffer(bool calledFromFinalizer = false)
694 {
695 if (_writePos == 0)
696 {
697 return;
698 }
699 if (_useAsyncIO)
700 {
702 if (!calledFromFinalizer)
703 {
704 task.GetAwaiter().GetResult();
705 }
706 }
707 else
708 {
710 }
711 _writePos = 0;
712 }
713
714 public override void SetLength(long value)
715 {
716 if (_writePos > 0)
717 {
719 }
720 else if (_readPos < _readLength)
721 {
723 }
724 _readPos = 0;
725 _readLength = 0;
726 if (_appendStart != -1 && value < _appendStart)
727 {
729 }
731 }
732
733 private void SetLengthCore(long value)
734 {
737 if (_filePosition > value)
738 {
740 }
741 }
742
744 {
745 bool flag = false;
746 int num = _readLength - _readPos;
747 if (num == 0)
748 {
749 if (!CanRead)
750 {
752 }
753 if (_writePos > 0)
754 {
756 }
757 if (!CanSeek || destination.Length >= _bufferLength)
758 {
759 num = ReadNative(destination);
760 _readPos = 0;
761 _readLength = 0;
762 return num;
763 }
764 num = ReadNative(GetBuffer());
765 if (num == 0)
766 {
767 return 0;
768 }
769 flag = num < _bufferLength;
770 _readPos = 0;
771 _readLength = num;
772 }
773 if (num > destination.Length)
774 {
775 num = destination.Length;
776 }
778 _readPos += num;
779 if (_fileHandle.CanSeek && num < destination.Length && !flag)
780 {
781 int num2 = ReadNative(destination.Slice(num));
782 num += num2;
783 _readPos = 0;
784 _readLength = 0;
785 }
786 return num;
787 }
788
790 {
791 if (!_useAsyncIO)
792 {
793 return ReadNative(_buffer);
794 }
796 }
797
798 private unsafe int ReadNative(Span<byte> buffer)
799 {
801 int errorCode;
802 int num = ReadFileNative(_fileHandle, buffer, null, out errorCode);
803 if (num == -1)
804 {
805 if (errorCode != 109)
806 {
807 if (errorCode == 87)
808 {
810 }
812 }
813 num = 0;
814 }
815 _filePosition += num;
816 return num;
817 }
818
819 public override long Seek(long offset, SeekOrigin origin)
820 {
821 if (origin < SeekOrigin.Begin || origin > SeekOrigin.End)
822 {
824 }
826 {
828 }
829 if (!CanSeek)
830 {
832 }
833 if (_writePos > 0)
834 {
836 }
837 else if (origin == SeekOrigin.Current)
838 {
840 }
841 _readPos = (_readLength = 0);
843 long num = _filePosition + (_readPos - _readLength);
844 long num2 = SeekCore(_fileHandle, offset, origin);
845 if (_appendStart != -1 && num2 < _appendStart)
846 {
847 SeekCore(_fileHandle, num, SeekOrigin.Begin);
849 }
850 if (_readLength > 0)
851 {
852 if (num == num2)
853 {
854 if (_readPos > 0)
855 {
858 _readPos = 0;
859 }
860 if (_readLength > 0)
861 {
863 }
864 }
865 else if (num - _readPos < num2 && num2 < num + _readLength - _readPos)
866 {
867 int num3 = (int)(num2 - num);
868 Buffer.BlockCopy(GetBuffer(), _readPos + num3, GetBuffer(), 0, _readLength - (_readPos + num3));
869 _readLength -= _readPos + num3;
870 _readPos = 0;
871 if (_readLength > 0)
872 {
874 }
875 }
876 else
877 {
878 _readPos = 0;
879 _readLength = 0;
880 }
881 }
882 return num2;
883 }
884
886 {
887 return Interlocked.CompareExchange(ref _currentOverlappedOwner, newSource, existingSource);
888 }
889
891 {
892 if (_writePos == 0)
893 {
894 if (!CanWrite)
895 {
897 }
898 if (_readPos < _readLength)
899 {
901 }
902 _readPos = 0;
903 _readLength = 0;
904 }
905 if (_writePos > 0)
906 {
907 int num = _bufferLength - _writePos;
908 if (num > 0)
909 {
910 if (num >= source.Length)
911 {
912 source.CopyTo(GetBuffer().AsSpan(_writePos));
913 _writePos += source.Length;
914 return;
915 }
916 source.Slice(0, num).CopyTo(GetBuffer().AsSpan(_writePos));
917 _writePos += num;
918 source = source.Slice(num);
919 }
921 _writePos = 0;
922 }
923 if (source.Length >= _bufferLength)
924 {
926 }
927 else if (source.Length != 0)
928 {
929 source.CopyTo(GetBuffer().AsSpan(_writePos));
930 _writePos = source.Length;
931 }
932 }
933
935 {
937 int errorCode;
938 int num = WriteFileNative(_fileHandle, source, null, out errorCode);
939 if (num == -1)
940 {
941 switch (errorCode)
942 {
943 case 232:
944 break;
945 case 87:
947 default:
949 }
950 num = 0;
951 }
952 _filePosition += num;
953 }
954
956 {
957 if (!CanRead)
958 {
960 }
961 if (!_fileHandle.CanSeek)
962 {
963 if (_readPos < _readLength)
964 {
965 int num = Math.Min(_readLength - _readPos, destination.Length);
967 _readPos += num;
968 synchronousResult = num;
969 return null;
970 }
971 synchronousResult = 0;
973 }
974 if (_writePos > 0)
975 {
977 }
978 if (_readPos == _readLength)
979 {
980 if (destination.Length < _bufferLength)
981 {
983 _readLength = task.GetAwaiter().GetResult();
984 int num2 = Math.Min(_readLength, destination.Length);
985 new Span<byte>(GetBuffer(), 0, num2).CopyTo(destination.Span);
986 _readPos = num2;
987 synchronousResult = num2;
988 return null;
989 }
990 _readPos = 0;
991 _readLength = 0;
992 synchronousResult = 0;
994 }
995 int num3 = Math.Min(_readLength - _readPos, destination.Length);
996 new Span<byte>(GetBuffer(), _readPos, num3).CopyTo(destination.Span);
997 _readPos += num3;
998 if (num3 == destination.Length)
999 {
1000 synchronousResult = num3;
1001 return null;
1002 }
1003 _readPos = 0;
1004 _readLength = 0;
1005 synchronousResult = 0;
1006 return ReadNativeAsync(destination.Slice(num3), num3, cancellationToken);
1007 }
1008
1010 {
1011 CompletionSource completionSource = CompletionSource.Create(this, _preallocatedOverlapped, numBufferedBytesRead, destination);
1012 NativeOverlapped* overlapped = completionSource.Overlapped;
1013 if (CanSeek)
1014 {
1015 long length = Length;
1017 if (_filePosition + destination.Length > length)
1018 {
1019 destination = ((_filePosition > length) ? default(Memory<byte>) : destination.Slice(0, (int)(length - _filePosition)));
1020 }
1021 overlapped->OffsetLow = (int)_filePosition;
1022 overlapped->OffsetHigh = (int)(_filePosition >> 32);
1023 SeekCore(_fileHandle, destination.Length, SeekOrigin.Current);
1024 }
1025 int errorCode;
1026 int num = ReadFileNative(_fileHandle, destination.Span, overlapped, out errorCode);
1027 if (num == -1)
1028 {
1029 switch (errorCode)
1030 {
1031 case 109:
1032 overlapped->InternalLow = IntPtr.Zero;
1033 completionSource.SetCompletedSynchronously(0);
1034 break;
1035 default:
1037 {
1038 SeekCore(_fileHandle, 0L, SeekOrigin.Current);
1039 }
1040 completionSource.ReleaseNativeResource();
1041 if (errorCode == 38)
1042 {
1044 break;
1045 }
1047 case 997:
1048 if (cancellationToken.CanBeCanceled)
1049 {
1051 }
1052 break;
1053 }
1054 }
1055 return completionSource.Task;
1056 }
1057
1059 {
1060 if (!CanWrite)
1061 {
1063 }
1064 bool flag = false;
1065 if (_fileHandle.CanSeek)
1066 {
1067 if (_writePos == 0)
1068 {
1069 if (_readPos < _readLength)
1070 {
1072 }
1073 _readPos = 0;
1074 _readLength = 0;
1075 }
1076 int num = _bufferLength - _writePos;
1077 if (source.Length < _bufferLength && !HasActiveBufferOperation && source.Length <= num)
1078 {
1079 source.Span.CopyTo(new Span<byte>(GetBuffer(), _writePos, source.Length));
1080 _writePos += source.Length;
1081 flag = true;
1082 if (source.Length != num)
1083 {
1084 return default(ValueTask);
1085 }
1086 }
1087 }
1088 Task task = null;
1089 if (_writePos > 0)
1090 {
1092 if (flag || task.IsFaulted || task.IsCanceled)
1093 {
1094 return new ValueTask(task);
1095 }
1096 }
1098 return new ValueTask((task == null || task.Status == TaskStatus.RanToCompletion) ? task2 : ((task2.Status == TaskStatus.RanToCompletion) ? task : Task.WhenAll(task, task2)));
1099 }
1100
1102 {
1104 NativeOverlapped* overlapped = completionSource.Overlapped;
1105 if (CanSeek)
1106 {
1107 long length = Length;
1109 if (_filePosition + source.Length > length)
1110 {
1112 }
1113 overlapped->OffsetLow = (int)_filePosition;
1114 overlapped->OffsetHigh = (int)(_filePosition >> 32);
1115 SeekCore(_fileHandle, source.Length, SeekOrigin.Current);
1116 }
1117 int errorCode;
1118 int num = WriteFileNative(_fileHandle, source.Span, overlapped, out errorCode);
1119 if (num == -1)
1120 {
1121 switch (errorCode)
1122 {
1123 case 232:
1124 completionSource.SetCompletedSynchronously(0);
1125 return Task.CompletedTask;
1126 default:
1128 {
1129 SeekCore(_fileHandle, 0L, SeekOrigin.Current);
1130 }
1131 completionSource.ReleaseNativeResource();
1132 if (errorCode == 38)
1133 {
1135 break;
1136 }
1138 case 997:
1139 if (cancellationToken.CanBeCanceled)
1140 {
1142 }
1143 break;
1144 }
1145 }
1146 return completionSource.Task;
1147 }
1148
1149 private unsafe int ReadFileNative(SafeFileHandle handle, Span<byte> bytes, NativeOverlapped* overlapped, out int errorCode)
1150 {
1151 return FileStreamHelpers.ReadFileNative(handle, bytes, overlapped, out errorCode);
1152 }
1153
1154 private unsafe int WriteFileNative(SafeFileHandle handle, ReadOnlySpan<byte> buffer, NativeOverlapped* overlapped, out int errorCode)
1155 {
1156 int numBytesWritten = 0;
1157 int num;
1158 fixed (byte* bytes = &MemoryMarshal.GetReference(buffer))
1159 {
1160 num = ((overlapped == null) ? Interop.Kernel32.WriteFile(handle, bytes, buffer.Length, out numBytesWritten, overlapped) : Interop.Kernel32.WriteFile(handle, bytes, buffer.Length, IntPtr.Zero, overlapped));
1161 }
1162 if (num == 0)
1163 {
1165 return -1;
1166 }
1167 errorCode = 0;
1168 return numBytesWritten;
1169 }
1170
1172 {
1173 if (!_useAsyncIO)
1174 {
1175 return base.CopyToAsync(destination, bufferSize, cancellationToken);
1176 }
1178 {
1180 }
1181 if (!CanRead)
1182 {
1184 }
1185 if (cancellationToken.IsCancellationRequested)
1186 {
1187 return Task.FromCanceled<int>(cancellationToken);
1188 }
1190 }
1191
1193 {
1194 if (_writePos > 0)
1195 {
1196 await FlushWriteAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
1197 }
1198 if (GetBuffer() != null)
1199 {
1200 int num = _readLength - _readPos;
1201 if (num > 0)
1202 {
1203 await destination.WriteAsync(new ReadOnlyMemory<byte>(GetBuffer(), _readPos, num), cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
1204 _readPos = (_readLength = 0);
1205 }
1206 }
1207 bool canSeek = CanSeek;
1208 if (canSeek)
1209 {
1211 }
1212 try
1213 {
1214 await FileStreamHelpers.AsyncModeCopyToAsync(_fileHandle, canSeek, _filePosition, destination, bufferSize, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
1215 }
1216 finally
1217 {
1219 {
1221 }
1222 }
1223 }
1224
1225 internal override void Lock(long position, long length)
1226 {
1228 }
1229
1230 internal override void Unlock(long position, long length)
1231 {
1233 }
1234}
static unsafe int WriteFile(IntPtr handle, byte *bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero)
static unsafe bool CancelIoEx(SafeHandle handle, NativeOverlapped *lpOverlapped)
static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize)
static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count)
Definition Buffer.cs:102
void SetCurrentStackTrace()
Definition Exception.cs:458
static void SuppressFinalize(object obj)
Definition GC.cs:202
Definition GC.cs:8
static string GetFullPath(string path)
Definition Path.cs:881
static unsafe long GetFileLength(SafeFileHandle handle)
static unsafe async Task AsyncModeCopyToAsync(SafeFileHandle handle, bool canSeek, long filePosition, Stream destination, int bufferSize, CancellationToken cancellationToken)
static int GetLastWin32ErrorAndDisposeHandleIfInvalid(SafeFileHandle handle)
static unsafe int ReadFileNative(SafeFileHandle handle, Span< byte > bytes, NativeOverlapped *overlapped, out int errorCode)
static void SetFileLength(SafeFileHandle handle, long length)
static void Lock(SafeFileHandle handle, bool canWrite, long position, long length)
static void Unlock(SafeFileHandle handle, long position, long length)
static void FlushToDisk(SafeFileHandle handle)
static long Seek(SafeFileHandle handle, long offset, SeekOrigin origin, bool closeInvalidHandle=false)
static bool IsIoRelatedException(Exception e)
static CompletionSource Create(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped preallocatedOverlapped, int numBufferedBytesRead, ReadOnlyMemory< byte > memory)
unsafe void RegisterForCancellation(CancellationToken cancellationToken)
unsafe CompletionSource(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped preallocatedOverlapped, int numBufferedBytes, byte[] bytes)
static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
MemoryFileStreamCompletionSource(Net5CompatFileStreamStrategy strategy, int numBufferedBytes, ReadOnlyMemory< byte > memory)
void InitFromHandle(SafeFileHandle handle, FileAccess access, bool useAsyncIO)
override long Seek(long offset, SeekOrigin origin)
override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
void Init(FileMode mode, string originalPath, FileOptions options)
override ValueTask WriteAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken=default(CancellationToken))
Net5CompatFileStreamStrategy(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize)
override void Write(byte[] buffer, int offset, int count)
async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
override int Read(byte[] buffer, int offset, int count)
Task FlushWriteAsync(CancellationToken cancellationToken)
CompletionSource CompareExchangeCurrentOverlappedOwner(CompletionSource newSource, CompletionSource existingSource)
override Task< int > ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Net5CompatFileStreamStrategy(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
unsafe int WriteFileNative(SafeFileHandle handle, ReadOnlySpan< byte > buffer, NativeOverlapped *overlapped, out int errorCode)
override ValueTask< int > ReadAsync(Memory< byte > buffer, CancellationToken cancellationToken=default(CancellationToken))
unsafe Task WriteAsyncInternalCore(ReadOnlyMemory< byte > source, CancellationToken cancellationToken)
Task< int > ReadAsyncTask(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
unsafe Task< int > ReadNativeAsync(Memory< byte > destination, int numBufferedBytesRead, CancellationToken cancellationToken)
override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
void InitFromHandleImpl(SafeFileHandle handle, bool useAsyncIO)
override Task FlushAsync(CancellationToken cancellationToken)
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
unsafe int ReadFileNative(SafeFileHandle handle, Span< byte > bytes, NativeOverlapped *overlapped, out int errorCode)
ValueTask WriteAsyncInternal(ReadOnlyMemory< byte > source, CancellationToken cancellationToken)
long SeekCore(SafeFileHandle fileHandle, long offset, SeekOrigin origin, bool closeInvalidHandle=false)
Task< int > ReadAsyncInternal(Memory< byte > destination, CancellationToken cancellationToken, out int synchronousResult)
Task FlushAsync()
Definition Stream.cs:669
void Dispose()
Definition Stream.cs:639
Task< int > BeginReadInternal(byte[] buffer, int offset, int count, AsyncCallback callback, object state, bool serializeAsynchronously, bool apm)
Definition Stream.cs:693
Task BeginWriteInternal(byte[] buffer, int offset, int count, AsyncCallback callback, object state, bool serializeAsynchronously, bool apm)
Definition Stream.cs:818
static Exception GetExceptionForWin32Error(int errorCode, string path="")
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static string IO_FileTooLongOrHandleNotSync
Definition SR.cs:1570
static string IO_SeekAppendOverwrite
Definition SR.cs:1576
static string IO_UnknownFileName
Definition SR.cs:1596
static string IO_SetLengthAppendTruncate
Definition SR.cs:1580
static string IO_FileStreamHandlePosition
Definition SR.cs:1564
static string Argument_InvalidSeekOrigin
Definition SR.cs:736
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
static int Exchange(ref int location1, int value)
static PreAllocatedOverlapped UnsafeCreate(IOCompletionCallback callback, object? state, object? pinData)
static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
Definition TaskToApm.cs:43
static void End(IAsyncResult asyncResult)
Definition TaskToApm.cs:48
new ConfiguredTaskAwaitable< TResult > ConfigureAwait(bool continueOnCapturedContext)
Definition Task.cs:226
static Task FromException(Exception exception)
Definition Task.cs:3341
static Task FromCanceled(CancellationToken cancellationToken)
Definition Task.cs:3363
static Task CompletedTask
Definition Task.cs:1120
new TaskAwaiter< TResult > GetAwaiter()
Definition Task.cs:221
static Task WhenAll(IEnumerable< Task > tasks)
Definition Task.cs:3504
unsafe void FreeNativeOverlapped(NativeOverlapped *overlapped)
unsafe NativeOverlapped * AllocateNativeOverlapped(IOCompletionCallback callback, object? state, object? pinData)
static unsafe? object GetNativeOverlappedState(NativeOverlapped *overlapped)
static void ThrowNotSupportedException_UnwritableStream()
static void ThrowArgumentException_HandleNotSync(string paramName)
static void ThrowNotSupportedException_UnseekableStream()
static void ThrowObjectDisposedException_FileClosed()
static void ThrowEndOfFileException()
static void ThrowNotSupportedException_UnreadableStream()
unsafe delegate void IOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOVERLAP)
static readonly IntPtr Zero
Definition IntPtr.cs:18
unsafe MemoryHandle Pin()
void CopyTo(Span< T > destination)
void CopyTo(Span< T > destination)
Definition Span.cs:224