443 begin(); |
443 begin(); |
444 |
444 |
445 // allocate OVERLAPPED |
445 // allocate OVERLAPPED |
446 overlapped = ioCache.add(result); |
446 overlapped = ioCache.add(result); |
447 |
447 |
448 // synchronize on result to allow this thread handle the case |
448 // initiate read |
449 // where the read completes immediately. |
449 n = readFile(handle, address, rem, position, overlapped); |
450 synchronized (result) { |
450 if (n == IOStatus.UNAVAILABLE) { |
451 n = readFile(handle, address, rem, position, overlapped); |
451 // I/O is pending |
452 if (n == IOStatus.UNAVAILABLE) { |
452 return; |
453 // I/O is pending |
453 } else if (n == IOStatus.EOF) { |
454 return; |
|
455 } |
|
456 // read completed immediately: |
|
457 // 1. update buffer position |
|
458 // 2. release waiters |
|
459 updatePosition(n); |
|
460 result.setResult(n); |
454 result.setResult(n); |
|
455 } else { |
|
456 throw new InternalError("Unexpected result: " + n); |
461 } |
457 } |
|
458 |
462 } catch (Throwable x) { |
459 } catch (Throwable x) { |
463 // failed to initiate read |
460 // failed to initiate read |
464 result.setFailure(toIOException(x)); |
461 result.setFailure(toIOException(x)); |
465 } finally { |
462 } finally { |
466 end(); |
463 end(); |
467 } |
464 } |
468 |
465 |
469 // read failed or EOF so completion port will not be notified |
466 // release resources |
470 if (n < 0 && overlapped != 0L) { |
467 if (overlapped != 0L) |
471 ioCache.remove(overlapped); |
468 ioCache.remove(overlapped); |
472 } |
|
473 |
|
474 // return direct buffer to cache if substituted |
|
475 releaseBufferIfSubstituted(); |
469 releaseBufferIfSubstituted(); |
476 |
470 |
477 // invoke completion handler |
471 // invoke completion handler |
478 Invoker.invoke(result); |
472 Invoker.invoke(result); |
479 } |
473 } |
632 begin(); |
626 begin(); |
633 |
627 |
634 // allocate an OVERLAPPED structure |
628 // allocate an OVERLAPPED structure |
635 overlapped = ioCache.add(result); |
629 overlapped = ioCache.add(result); |
636 |
630 |
637 // synchronize on result to allow this thread handle the case |
631 // initiate the write |
638 // where the read completes immediately. |
632 n = writeFile(handle, address, rem, position, overlapped); |
639 synchronized (result) { |
633 if (n == IOStatus.UNAVAILABLE) { |
640 n = writeFile(handle, address, rem, position, overlapped); |
634 // I/O is pending |
641 if (n == IOStatus.UNAVAILABLE) { |
635 return; |
642 // I/O is pending |
636 } else { |
643 return; |
637 throw new InternalError("Unexpected result: " + n); |
644 } |
|
645 // read completed immediately: |
|
646 // 1. update buffer position |
|
647 // 2. release waiters |
|
648 updatePosition(n); |
|
649 result.setResult(n); |
|
650 } |
638 } |
|
639 |
651 } catch (Throwable x) { |
640 } catch (Throwable x) { |
652 // failed to initiate read: |
641 // failed to initiate read: |
653 result.setFailure(toIOException(x)); |
642 result.setFailure(toIOException(x)); |
654 |
643 |
655 // release resources |
644 // release resources |