Index: sdk/lib/io/file_impl.dart |
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart |
index 1dce796efc46c74f6049a15b331138c286971bf2..4df878a9844a6c05bcca5ab1bc08dff04c9ce4ad 100644 |
--- a/sdk/lib/io/file_impl.dart |
+++ b/sdk/lib/io/file_impl.dart |
@@ -531,17 +531,13 @@ class _File extends FileSystemEntity implements File { |
class _RandomAccessFile implements RandomAccessFile { |
final String path; |
int _id; |
+ bool _asyncDispatched = false; |
SendPort _fileService; |
_RandomAccessFile(int this._id, String this.path); |
Future<RandomAccessFile> close() { |
- if (closed) return _closedException(); |
- // Set the id_ to 0 (NULL) to ensure the no more async requests |
- // can be issued for this file. |
- int id = _id; |
- _id = 0; |
- return _IOService.dispatch(_FILE_CLOSE, [id]).then((result) { |
+ return _dispatch(_FILE_CLOSE, [_id], markClosed: true).then((result) { |
if (result != -1) { |
_id = result; |
return this; |
@@ -554,7 +550,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static int _close(int id); |
void closeSync() { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var id = _close(_id); |
if (id == -1) { |
throw new FileException("Cannot close file", path); |
@@ -563,8 +559,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<int> readByte() { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_READ_BYTE, [_id]).then((response) { |
+ return _dispatch(_FILE_READ_BYTE, [_id]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "readByte failed", path); |
} |
@@ -575,7 +570,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _readByte(int id); |
int readByteSync() { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _readByte(_id); |
if (result is OSError) { |
throw new FileException("readByte failed", path, result); |
@@ -587,8 +582,7 @@ class _RandomAccessFile implements RandomAccessFile { |
if (bytes is !int) { |
throw new ArgumentError(bytes); |
} |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_READ, [_id, bytes]).then((response) { |
+ return _dispatch(_FILE_READ, [_id, bytes]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "read failed", path); |
} |
@@ -599,7 +593,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _read(int id, int bytes); |
List<int> readSync(int bytes) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
if (bytes is !int) { |
throw new ArgumentError(bytes); |
} |
@@ -616,11 +610,10 @@ class _RandomAccessFile implements RandomAccessFile { |
(end != null && end is !int)) { |
throw new ArgumentError(); |
} |
- if (closed) return _closedException(); |
if (start == null) start = 0; |
if (end == null) end = buffer.length; |
int length = end - start; |
- return _IOService.dispatch(_FILE_READ_INTO, [_id, length]).then((response) { |
+ return _dispatch(_FILE_READ_INTO, [_id, length]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "readInto failed", path); |
} |
@@ -642,7 +635,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _readInto(int id, List<int> buffer, int start, int end); |
int readIntoSync(List<int> buffer, [int start, int end]) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
if (buffer is !List || |
(start != null && start is !int) || |
(end != null && end is !int)) { |
@@ -663,8 +656,7 @@ class _RandomAccessFile implements RandomAccessFile { |
if (value is !int) { |
throw new ArgumentError(value); |
} |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) { |
+ return _dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "writeByte failed", path); |
} |
@@ -675,7 +667,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _writeByte(int id, int value); |
int writeByteSync(int value) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
if (value is !int) { |
throw new ArgumentError(value); |
} |
@@ -693,8 +685,6 @@ class _RandomAccessFile implements RandomAccessFile { |
throw new ArgumentError("Invalid arguments to writeFrom"); |
} |
- if (closed) return _closedException(); |
- |
_BufferAndStart result; |
try { |
result = _ensureFastAndSerializableByteData(buffer, start, end); |
@@ -707,7 +697,7 @@ class _RandomAccessFile implements RandomAccessFile { |
request[1] = result.buffer; |
request[2] = result.start; |
request[3] = end - (start - result.start); |
- return _IOService.dispatch(_FILE_WRITE_FROM, request).then((response) { |
+ return _dispatch(_FILE_WRITE_FROM, request).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "writeFrom failed", path); |
} |
@@ -718,7 +708,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _writeFrom(int id, List<int> buffer, int start, int end); |
void writeFromSync(List<int> buffer, [int start, int end]) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
if (buffer is !List || |
(start != null && start is !int) || |
(end != null && end is !int)) { |
@@ -757,8 +747,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<int> position() { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_POSITION, [_id]).then((response) { |
+ return _dispatch(_FILE_POSITION, [_id]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "position failed", path); |
} |
@@ -769,7 +758,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _position(int id); |
int positionSync() { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _position(_id); |
if (result is OSError) { |
throw new FileException("position failed", path, result); |
@@ -778,8 +767,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<RandomAccessFile> setPosition(int position) { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_SET_POSITION, [_id, position]) |
+ return _dispatch(_FILE_SET_POSITION, [_id, position]) |
.then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "setPosition failed", path); |
@@ -791,7 +779,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _setPosition(int id, int position); |
void setPositionSync(int position) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _setPosition(_id, position); |
if (result is OSError) { |
throw new FileException("setPosition failed", path, result); |
@@ -799,8 +787,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<RandomAccessFile> truncate(int length) { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_TRUNCATE, [_id, length]).then((response) { |
+ return _dispatch(_FILE_TRUNCATE, [_id, length]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "truncate failed", path); |
} |
@@ -811,7 +798,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _truncate(int id, int length); |
void truncateSync(int length) { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _truncate(_id, length); |
if (result is OSError) { |
throw new FileException("truncate failed", path, result); |
@@ -819,8 +806,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<int> length() { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_LENGTH, [_id]).then((response) { |
+ return _dispatch(_FILE_LENGTH, [_id]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, "length failed", path); |
} |
@@ -831,7 +817,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _length(int id); |
int lengthSync() { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _length(_id); |
if (result is OSError) { |
throw new FileException("length failed", path, result); |
@@ -840,8 +826,7 @@ class _RandomAccessFile implements RandomAccessFile { |
} |
Future<RandomAccessFile> flush() { |
- if (closed) return _closedException(); |
- return _IOService.dispatch(_FILE_FLUSH, [_id]).then((response) { |
+ return _dispatch(_FILE_FLUSH, [_id]).then((response) { |
if (_isErrorResponse(response)) { |
throw _exceptionFromResponse(response, |
"flush failed", |
@@ -854,7 +839,7 @@ class _RandomAccessFile implements RandomAccessFile { |
external static _flush(int id); |
void flushSync() { |
- _checkNotClosed(); |
+ _checkAvailable(); |
var result = _flush(_id); |
if (result is OSError) { |
throw new FileException("flush failed", path, result); |
@@ -863,13 +848,32 @@ class _RandomAccessFile implements RandomAccessFile { |
bool get closed => _id == 0; |
- void _checkNotClosed() { |
+ Future _dispatch(int request, List data, { bool markClosed: false }) { |
if (closed) { |
- throw new FileException("File closed", path); |
+ return new Future.error(new FileException("File closed", path)); |
+ } |
+ if (_asyncDispatched) { |
+ var msg = "An async operation is currently pending"; |
+ return new Future.error(new FileException(msg, path)); |
} |
+ if (markClosed) { |
+ // Set the id_ to 0 (NULL) to ensure the no more async requests |
+ // can be issued for this file. |
+ _id = 0; |
+ } |
+ _asyncDispatched = true; |
+ return _IOService.dispatch(request, data) |
+ .whenComplete(() { |
+ _asyncDispatched = false; |
+ }); |
} |
- Future _closedException() { |
- return new Future.error(new FileException("File closed", path)); |
+ void _checkAvailable() { |
+ if (_asyncDispatched) { |
+ throw new FileException("An async operation is currently pending", path); |
+ } |
+ if (closed) { |
+ throw new FileException("File closed", path); |
+ } |
} |
} |