@@ -13,8 +13,8 @@ internal sealed partial class AsyncWindowsFileStreamStrategy : WindowsFileStream
13
13
private PreAllocatedOverlapped ? _preallocatedOverlapped ; // optimization for async ops to avoid per-op allocations
14
14
private FileStreamCompletionSource ? _currentOverlappedOwner ; // async op currently using the preallocated overlapped
15
15
16
- internal AsyncWindowsFileStreamStrategy ( SafeFileHandle handle , FileAccess access )
17
- : base ( handle , access )
16
+ internal AsyncWindowsFileStreamStrategy ( SafeFileHandle handle , FileAccess access , FileShare share )
17
+ : base ( handle , access , share )
18
18
{
19
19
}
20
20
@@ -98,7 +98,6 @@ protected override void OnInit()
98
98
if ( _fileHandle . ThreadPoolBinding == null )
99
99
{
100
100
// We should close the handle so that the handle is not open until SafeFileHandle GC
101
- Debug . Assert ( ! _exposedHandle , "Are we closing handle that we exposed/not own, how?" ) ;
102
101
_fileHandle . Dispose ( ) ;
103
102
}
104
103
}
@@ -142,18 +141,16 @@ private unsafe Task<int> ReadAsyncInternal(Memory<byte> destination, Cancellatio
142
141
NativeOverlapped * intOverlapped = completionSource . Overlapped ;
143
142
144
143
// Calculate position in the file we should be at after the read is done
144
+ long positionBefore = _filePosition ;
145
145
if ( CanSeek )
146
146
{
147
147
long len = Length ;
148
148
149
- // Make sure we are reading from the position that we think we are
150
- VerifyOSHandlePosition ( ) ;
151
-
152
- if ( destination . Length > len - _filePosition )
149
+ if ( positionBefore + destination . Length > len )
153
150
{
154
- if ( _filePosition <= len )
151
+ if ( positionBefore <= len )
155
152
{
156
- destination = destination . Slice ( 0 , ( int ) ( len - _filePosition ) ) ;
153
+ destination = destination . Slice ( 0 , ( int ) ( len - positionBefore ) ) ;
157
154
}
158
155
else
159
156
{
@@ -163,23 +160,17 @@ private unsafe Task<int> ReadAsyncInternal(Memory<byte> destination, Cancellatio
163
160
164
161
// Now set the position to read from in the NativeOverlapped struct
165
162
// For pipes, we should leave the offset fields set to 0.
166
- intOverlapped ->OffsetLow = unchecked ( ( int ) _filePosition ) ;
167
- intOverlapped ->OffsetHigh = ( int ) ( _filePosition >> 32 ) ;
163
+ intOverlapped ->OffsetLow = unchecked ( ( int ) positionBefore ) ;
164
+ intOverlapped ->OffsetHigh = ( int ) ( positionBefore >> 32 ) ;
168
165
169
166
// When using overlapped IO, the OS is not supposed to
170
167
// touch the file pointer location at all. We will adjust it
171
- // ourselves. This isn't threadsafe.
172
-
173
- // WriteFile should not update the file pointer when writing
174
- // in overlapped mode, according to MSDN. But it does update
175
- // the file pointer when writing to a UNC path!
176
- // So changed the code below to seek to an absolute
177
- // location, not a relative one. ReadFile seems consistent though.
178
- SeekCore ( _fileHandle , destination . Length , SeekOrigin . Current ) ;
168
+ // ourselves, but only in memory. This isn't threadsafe.
169
+ _filePosition += destination . Length ;
179
170
}
180
171
181
172
// queue an async ReadFile operation and pass in a packed overlapped
182
- int r = FileStreamHelpers . ReadFileNative ( _fileHandle , destination . Span , intOverlapped , out int errorCode ) ;
173
+ int r = FileStreamHelpers . ReadFileNative ( _fileHandle , destination . Span , false , intOverlapped , out int errorCode ) ;
183
174
184
175
// ReadFile, the OS version, will return 0 on failure. But
185
176
// my ReadFileNative wrapper returns -1. My wrapper will return
@@ -208,7 +199,7 @@ private unsafe Task<int> ReadAsyncInternal(Memory<byte> destination, Cancellatio
208
199
{
209
200
if ( ! _fileHandle . IsClosed && CanSeek ) // Update Position - It could be anywhere.
210
201
{
211
- SeekCore ( _fileHandle , 0 , SeekOrigin . Current ) ;
202
+ _filePosition = positionBefore ;
212
203
}
213
204
214
205
completionSource . ReleaseNativeResource ( ) ;
@@ -269,32 +260,23 @@ private unsafe Task WriteAsyncInternalCore(ReadOnlyMemory<byte> source, Cancella
269
260
FileStreamCompletionSource completionSource = FileStreamCompletionSource . Create ( this , _preallocatedOverlapped , 0 , source ) ;
270
261
NativeOverlapped * intOverlapped = completionSource . Overlapped ;
271
262
263
+ long positionBefore = _filePosition ;
272
264
if ( CanSeek )
273
265
{
274
- // Make sure we set the length of the file appropriately.
275
- long len = Length ;
276
-
277
- // Make sure we are writing to the position that we think we are
278
- VerifyOSHandlePosition ( ) ;
279
-
280
- if ( _filePosition + source . Length > len )
281
- {
282
- SetLengthCore ( _filePosition + source . Length ) ;
283
- }
284
-
285
266
// Now set the position to read from in the NativeOverlapped struct
286
267
// For pipes, we should leave the offset fields set to 0.
287
- intOverlapped ->OffsetLow = ( int ) _filePosition ;
288
- intOverlapped ->OffsetHigh = ( int ) ( _filePosition >> 32 ) ;
268
+ intOverlapped ->OffsetLow = ( int ) positionBefore ;
269
+ intOverlapped ->OffsetHigh = ( int ) ( positionBefore >> 32 ) ;
289
270
290
271
// When using overlapped IO, the OS is not supposed to
291
272
// touch the file pointer location at all. We will adjust it
292
- // ourselves. This isn't threadsafe.
293
- SeekCore ( _fileHandle , source . Length , SeekOrigin . Current ) ;
273
+ // ourselves, but only in memory. This isn't threadsafe.
274
+ _filePosition += source . Length ;
275
+ UpdateLengthOnChangePosition ( ) ;
294
276
}
295
277
296
278
// queue an async WriteFile operation and pass in a packed overlapped
297
- int r = FileStreamHelpers . WriteFileNative ( _fileHandle , source . Span , intOverlapped , out int errorCode ) ;
279
+ int r = FileStreamHelpers . WriteFileNative ( _fileHandle , source . Span , false , intOverlapped , out int errorCode ) ;
298
280
299
281
// WriteFile, the OS version, will return 0 on failure. But
300
282
// my WriteFileNative wrapper returns -1. My wrapper will return
@@ -320,7 +302,7 @@ private unsafe Task WriteAsyncInternalCore(ReadOnlyMemory<byte> source, Cancella
320
302
{
321
303
if ( ! _fileHandle . IsClosed && CanSeek ) // Update Position - It could be anywhere.
322
304
{
323
- SeekCore ( _fileHandle , 0 , SeekOrigin . Current ) ;
305
+ _filePosition = positionBefore ;
324
306
}
325
307
326
308
completionSource . ReleaseNativeResource ( ) ;
@@ -382,24 +364,18 @@ private async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, Canc
382
364
Debug . Assert ( ! _fileHandle . IsClosed , "!_handle.IsClosed" ) ;
383
365
Debug . Assert ( CanRead , "_parent.CanRead" ) ;
384
366
385
- bool canSeek = CanSeek ;
386
- if ( canSeek )
387
- {
388
- VerifyOSHandlePosition ( ) ;
389
- }
390
-
391
367
try
392
368
{
393
369
await FileStreamHelpers
394
- . AsyncModeCopyToAsync ( _fileHandle , _path , canSeek , _filePosition , destination , bufferSize , cancellationToken )
370
+ . AsyncModeCopyToAsync ( _fileHandle , _path , CanSeek , _filePosition , destination , bufferSize , cancellationToken )
395
371
. ConfigureAwait ( false ) ;
396
372
}
397
373
finally
398
374
{
399
375
// Make sure the stream's current position reflects where we ended up
400
- if ( ! _fileHandle . IsClosed && canSeek )
376
+ if ( ! _fileHandle . IsClosed && CanSeek )
401
377
{
402
- SeekCore ( _fileHandle , 0 , SeekOrigin . End ) ;
378
+ _filePosition = Length ;
403
379
}
404
380
}
405
381
}
0 commit comments