@@ -346,27 +346,63 @@ impl File {
346
346
self . fsync ( )
347
347
}
348
348
349
- pub fn lock ( & self ) -> io:: Result < ( ) > {
350
- cvt ( unsafe {
351
- let mut overlapped = mem:: zeroed ( ) ;
352
- c:: LockFileEx (
349
+ fn acquire_lock ( & self , flags : c:: LOCK_FILE_FLAGS ) -> io:: Result < ( ) > {
350
+ unsafe {
351
+ let mut overlapped: c:: OVERLAPPED = mem:: zeroed ( ) ;
352
+ let event = c:: CreateEventW ( ptr:: null_mut ( ) , c:: FALSE , c:: FALSE , ptr:: null ( ) ) ;
353
+ if event. is_null ( ) {
354
+ return Err ( io:: Error :: last_os_error ( ) ) ;
355
+ }
356
+ overlapped. hEvent = event;
357
+ let lock_result = cvt ( c:: LockFileEx (
353
358
self . handle . as_raw_handle ( ) ,
354
- c :: LOCKFILE_EXCLUSIVE_LOCK ,
359
+ flags ,
355
360
0 ,
356
361
u32:: MAX ,
357
362
u32:: MAX ,
358
363
& mut overlapped,
359
- )
360
- } ) ?;
361
- Ok ( ( ) )
364
+ ) ) ;
365
+
366
+ let final_result = match lock_result {
367
+ Ok ( _) => Ok ( ( ) ) ,
368
+ Err ( err) => {
369
+ if err. raw_os_error ( ) == Some ( c:: ERROR_IO_PENDING as i32 ) {
370
+ // Wait for the lock to be acquired. This can happen asynchronously,
371
+ // if the file handle was opened for async IO
372
+ let wait_result = c:: WaitForSingleObject ( overlapped. hEvent , c:: INFINITE ) ;
373
+ if wait_result == c:: WAIT_OBJECT_0 {
374
+ // Wait completed successfully, get the lock operation status
375
+ let mut bytes_transferred = 0 ;
376
+ cvt ( c:: GetOverlappedResult (
377
+ self . handle . as_raw_handle ( ) ,
378
+ & mut overlapped,
379
+ & mut bytes_transferred,
380
+ c:: TRUE ,
381
+ ) )
382
+ . map ( |_| ( ) )
383
+ } else if wait_result == c:: WAIT_FAILED {
384
+ // Wait failed
385
+ Err ( io:: Error :: last_os_error ( ) )
386
+ } else {
387
+ // WAIT_ABANDONED and WAIT_TIMEOUT should not be possible
388
+ unreachable ! ( )
389
+ }
390
+ } else {
391
+ Err ( err)
392
+ }
393
+ }
394
+ } ;
395
+ c:: CloseHandle ( overlapped. hEvent ) ;
396
+ final_result
397
+ }
398
+ }
399
+
400
+ pub fn lock ( & self ) -> io:: Result < ( ) > {
401
+ self . acquire_lock ( c:: LOCKFILE_EXCLUSIVE_LOCK )
362
402
}
363
403
364
404
pub fn lock_shared ( & self ) -> io:: Result < ( ) > {
365
- cvt ( unsafe {
366
- let mut overlapped = mem:: zeroed ( ) ;
367
- c:: LockFileEx ( self . handle . as_raw_handle ( ) , 0 , 0 , u32:: MAX , u32:: MAX , & mut overlapped)
368
- } ) ?;
369
- Ok ( ( ) )
405
+ self . acquire_lock ( 0 )
370
406
}
371
407
372
408
pub fn try_lock ( & self ) -> io:: Result < bool > {
0 commit comments