Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: runtime/bin/file_impl.dart

Issue 9415043: Port async file operations to be using native ports instead or an isolate (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed remaining issues Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class _FileInputStream extends _BaseDataInputStream implements InputStream { 5 class _FileInputStream extends _BaseDataInputStream implements InputStream {
6 _FileInputStream(RandomAccessFile this._file, int this._length) { 6 _FileInputStream(RandomAccessFile this._file, int this._length) {
7 _streamMarkedClosed = true; 7 _streamMarkedClosed = true;
8 _checkScheduleCallbacks(); 8 _checkScheduleCallbacks();
9 } 9 }
10 10
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 // the stream is fully closed. 149 // the stream is fully closed.
150 bool _closeCallbackCalled = false; 150 bool _closeCallbackCalled = false;
151 151
152 Timer _scheduledNoPendingWriteCallback; 152 Timer _scheduledNoPendingWriteCallback;
153 Timer _scheduledCloseCallback; 153 Timer _scheduledCloseCallback;
154 Function _noPendingWriteHandler; 154 Function _noPendingWriteHandler;
155 Function _closeHandler; 155 Function _closeHandler;
156 } 156 }
157 157
158 158
159 class _FileOperation {
160 abstract void execute(ReceivePort port);
161
162 void set replyPort(SendPort port) {
163 _replyPort = port;
164 }
165
166 bool isWrite() => false;
167
168 SendPort _replyPort;
169 }
170
171
172 class _ExistsOperation extends _FileOperation {
173 _ExistsOperation(String this._name);
174
175 void execute(ReceivePort port) {
176 _replyPort.send(_FileUtils.exists(_name), port.toSendPort());
177 }
178
179 String _name;
180 }
181
182
183 class _OpenOperation extends _FileOperation {
184 _OpenOperation(String this._name, int this._mode);
185
186 void execute(ReceivePort port) {
187 _replyPort.send(_FileUtils.checkedOpen(_name, _mode),
188 port.toSendPort());
189 }
190
191 String _name;
192 int _mode;
193 }
194
195
196 class _CloseOperation extends _FileOperation {
197 _CloseOperation(int this._id);
198
199 void execute(ReceivePort port) {
200 _replyPort.send(_FileUtils.close(_id), port.toSendPort());
201 }
202
203 int _id;
204 }
205
206
207 class _ReadByteOperation extends _FileOperation {
208 _ReadByteOperation(int this._id);
209
210 void execute(ReceivePort port) {
211 _replyPort.send(_FileUtils.readByte(_id), port.toSendPort());
212 }
213
214 int _id;
215 }
216
217
218 class _ReadListResult {
219 _ReadListResult(this.read, this.buffer);
220 int read;
221 List buffer;
222 }
223
224
225 class _ReadListOperation extends _FileOperation {
226 _ReadListOperation(int this._id,
227 int this._length,
228 int this._offset,
229 int this._bytes);
230
231 void execute(ReceivePort port) {
232 if (_bytes == 0) {
233 _replyPort.send(0, port.toSendPort());
234 return;
235 }
236 int index =
237 _FileUtils.checkReadWriteListArguments(_length, _offset, _bytes);
238 if (index != 0) {
239 _replyPort.send("index out of range in readList: $index",
240 port.toSendPort());
241 return;
242 }
243 ByteArray buffer = new ByteArray(_bytes);
244 var result =
245 new _ReadListResult(_FileUtils.readList(_id, buffer, 0, _bytes),
246 buffer);
247 _replyPort.send(result, port.toSendPort());
248 }
249
250 int _id;
251 int _length;
252 int _offset;
253 int _bytes;
254 }
255
256
257 class _WriteByteOperation extends _FileOperation {
258 _WriteByteOperation(int this._id, int this._value);
259
260 void execute(ReceivePort port) {
261 _replyPort.send(_FileUtils.writeByte(_id, _value), port.toSendPort());
262 }
263
264 bool isWrite() => true;
265
266 int _id;
267 int _value;
268 }
269
270
271 class _WriteListOperation extends _FileOperation {
272 _WriteListOperation(int this._id,
273 List this._buffer,
274 int this._offset,
275 int this._bytes);
276
277 void execute(ReceivePort port) {
278 if (_bytes == 0) {
279 _replyPort.send(0, port.toSendPort());
280 return;
281 }
282 int index =
283 _FileUtils.checkReadWriteListArguments(_buffer.length, _offset, _bytes);
284 if (index != 0) {
285 _replyPort.send("index out of range in writeList: $index",
286 port.toSendPort());
287 return;
288 }
289 var result = _FileUtils.writeList(_id, _buffer, _offset, _bytes);
290 _replyPort.send(result, port.toSendPort());
291 }
292
293 bool isWrite() => true;
294
295 int _id;
296 List _buffer;
297 int _offset;
298 int _bytes;
299 }
300
301
302 class _WriteStringOperation extends _FileOperation {
303 _WriteStringOperation(int this._id, String this._string);
304
305 void execute(ReceivePort port) {
306 _replyPort.send(_FileUtils.checkedWriteString(_id, _string),
307 port.toSendPort());
308 }
309
310 bool isWrite() => true;
311
312 int _id;
313 String _string;
314 }
315
316
317 class _PositionOperation extends _FileOperation {
318 _PositionOperation(int this._id);
319
320 void execute(ReceivePort port) {
321 _replyPort.send(_FileUtils.position(_id), port.toSendPort());
322 }
323
324 int _id;
325 }
326
327
328 class _SetPositionOperation extends _FileOperation {
329 _SetPositionOperation(int this._id, int this._position);
330
331 void execute(ReceivePort port) {
332 _replyPort.send(_FileUtils.setPosition(_id, _position), port.toSendPort());
333 }
334
335 int _id;
336 int _position;
337 }
338
339
340 class _TruncateOperation extends _FileOperation {
341 _TruncateOperation(int this._id, int this._length);
342
343 void execute(ReceivePort port) {
344 _replyPort.send(_FileUtils.truncate(_id, _length), port.toSendPort());
345 }
346
347 int _id;
348 int _length;
349 }
350
351
352 class _LengthOperation extends _FileOperation {
353 _LengthOperation(int this._id);
354
355 void execute(ReceivePort port) {
356 _replyPort.send(_FileUtils.length(_id), port.toSendPort());
357 }
358
359 int _id;
360 }
361
362
363 class _FlushOperation extends _FileOperation {
364 _FlushOperation(int this._id);
365
366 void execute(ReceivePort port) {
367 _replyPort.send(_FileUtils.flush(_id), port.toSendPort());
368 }
369
370 int _id;
371 }
372
373
374 class _FullPathOperation extends _FileOperation {
375 _FullPathOperation(String this._name);
376
377 void execute(ReceivePort port) {
378 _replyPort.send(_FileUtils.checkedFullPath(_name), port.toSendPort());
379 }
380
381 String _name;
382 }
383
384
385 class _CreateOperation extends _FileOperation {
386 _CreateOperation(String this._name);
387
388 void execute(ReceivePort port) {
389 _replyPort.send(_FileUtils.checkedCreate(_name), port.toSendPort());
390 }
391
392 String _name;
393 }
394
395
396 class _DeleteOperation extends _FileOperation {
397 _DeleteOperation(String this._name);
398
399 void execute(ReceivePort port) {
400 _replyPort.send(_FileUtils.checkedDelete(_name), port.toSendPort());
401 }
402
403 String _name;
404 }
405
406
407 class _ExitOperation extends _FileOperation {
408 void execute(ReceivePort port) {
409 port.close();
410 }
411 }
412
413
414 class _FileOperationIsolate extends Isolate {
415 _FileOperationIsolate() : super.heavy();
416
417 void handleOperation(_FileOperation message, SendPort ignored) {
418 message.execute(port);
419 port.receive(handleOperation);
420 }
421
422 void main() {
423 port.receive(handleOperation);
424 }
425 }
426
427
428 class _FileOperationScheduler {
429 _FileOperationScheduler() : _queue = new Queue();
430
431 void schedule(SendPort port) {
432 assert(_isolate != null);
433 if (_queue.isEmpty()) {
434 port.send(new _ExitOperation());
435 _isolate = null;
436 } else {
437 port.send(_queue.removeFirst());
438 }
439 }
440
441 void scheduleWrap(void callback(result, ignored)) {
442 return (result, replyTo) {
443 callback(result, replyTo);
444 schedule(replyTo);
445 };
446 }
447
448 void enqueue(_FileOperation operation, void callback(result, ignored)) {
449 ReceivePort replyPort = new ReceivePort.singleShot();
450 replyPort.receive(scheduleWrap(callback));
451 operation.replyPort = replyPort.toSendPort();
452 _queue.addLast(operation);
453 if (_isolate == null) {
454 _isolate = new _FileOperationIsolate();
455 _isolate.spawn().then((port) {
456 schedule(port);
457 });
458 }
459 }
460
461 bool noPendingWrite() {
462 int queuedWrites = 0;
463 _queue.forEach((operation) {
464 if (operation.isWrite()) {
465 queuedWrites++;
466 }
467 });
468 return queuedWrites == 0;
469 }
470
471 Queue<_FileOperation> _queue;
472 _FileOperationIsolate _isolate;
473 }
474
475
476 // Helper class containing static file helper methods. 159 // Helper class containing static file helper methods.
477 class _FileUtils { 160 class _FileUtils {
478 static bool exists(String name) native "File_Exists"; 161 static final kExistsRequest = 0;
479 static int open(String name, int mode) native "File_Open"; 162 static final kCreateRequest = 1;
480 static bool create(String name) native "File_Create"; 163 static final kDeleteRequest = 2;
481 static bool delete(String name) native "File_Delete"; 164 static final kOpenRequest = 3;
482 static String fullPath(String name) native "File_FullPath"; 165 static final kFullPathRequest = 4;
483 static int close(int id) native "File_Close"; 166 static final kCloseRequest = 5;
484 static int readByte(int id) native "File_ReadByte"; 167 static final kPositionRequest = 6;
485 static int readList(int id, List<int> buffer, int offset, int bytes) 168 static final kSetPositionRequest = 7;
486 native "File_ReadList"; 169 static final kTruncateRequest = 8;
487 static int writeByte(int id, int value) native "File_WriteByte"; 170 static final kLengthRequest = 9;
488 static int writeList(int id, List<int> buffer, int offset, int bytes) { 171 static final kFlushRequest = 10;
172 static final kReadByteRequest = 11;
173 static final kWriteByteRequest = 12;
174 static final kReadListRequest = 13;
175 static final kWriteListRequest = 14;
176 static final kWriteStringRequest = 15;
177
178 static List ensureFastAndSerializabelBuffer(
Mads Ager (google) 2012/02/23 08:57:44 Serializable
Søren Gjesse 2012/02/23 10:26:42 Done.
179 List buffer, int offset, int bytes) {
489 // When using the Dart C API to access raw data, using a ByteArray is 180 // When using the Dart C API to access raw data, using a ByteArray is
490 // currently much faster. This function will make a copy of the 181 // currently much faster. This function will make a copy of the
491 // supplied List to a ByteArray if it isn't already. 182 // supplied List to a ByteArray if it isn't already.
492 List outBuffer; 183 List outBuffer;
493 int outOffset = offset; 184 int outOffset = offset;
494 if (buffer is ByteArray || buffer is ObjectArray) { 185 if (buffer is ByteArray || buffer is ObjectArray) {
495 outBuffer = buffer; 186 outBuffer = buffer;
496 } else { 187 } else {
497 outBuffer = new ByteArray(bytes); 188 outBuffer = new ByteArray(bytes);
498 outOffset = 0; 189 outOffset = 0;
499 int j = offset; 190 int j = offset;
500 for (int i = 0; i < bytes; i++) { 191 for (int i = 0; i < bytes; i++) {
501 int value = buffer[j]; 192 int value = buffer[j];
502 if (value is! int) { 193 if (value is! int) {
503 throw new FileIOException( 194 throw new FileIOException(
504 "List element is not an integer at index $j"); 195 "List element is not an integer at index $j");
505 } 196 }
506 outBuffer[i] = value; 197 outBuffer[i] = value;
507 j++; 198 j++;
508 } 199 }
509 } 200 }
201 return [outBuffer, outOffset];
202 }
203
204 static bool exists(String name) native "File_Exists";
205 static int open(String name, int mode) native "File_Open";
206 static bool create(String name) native "File_Create";
207 static bool delete(String name) native "File_Delete";
208 static String fullPath(String name) native "File_FullPath";
209 static int close(int id) native "File_Close";
210 static int readByte(int id) native "File_ReadByte";
211 static int readList(int id, List<int> buffer, int offset, int bytes)
212 native "File_ReadList";
213 static int writeByte(int id, int value) native "File_WriteByte";
214 static int writeList(int id, List<int> buffer, int offset, int bytes) {
215 List result =
216 _FileUtils.ensureFastAndSerializabelBuffer(buffer, offset, bytes);
217 List outBuffer = result[0];
218 int outOffset = result[1];
510 return writeListNative(id, outBuffer, outOffset, bytes); 219 return writeListNative(id, outBuffer, outOffset, bytes);
511 } 220 }
512 static int writeListNative(int id, List<int> buffer, int offset, int bytes) 221 static int writeListNative(int id, List<int> buffer, int offset, int bytes)
513 native "File_WriteList"; 222 native "File_WriteList";
514 static int writeString(int id, String string) native "File_WriteString"; 223 static int writeString(int id, String string) native "File_WriteString";
515 static int position(int id) native "File_Position"; 224 static int position(int id) native "File_Position";
516 static bool setPosition(int id, int position) native "File_SetPosition"; 225 static bool setPosition(int id, int position) native "File_SetPosition";
517 static bool truncate(int id, int length) native "File_Truncate"; 226 static bool truncate(int id, int length) native "File_Truncate";
518 static int length(int id) native "File_Length"; 227 static int length(int id) native "File_Length";
519 static int flush(int id) native "File_Flush"; 228 static int flush(int id) native "File_Flush";
520 static int openStdio(int fd) native "File_OpenStdio"; 229 static int openStdio(int fd) native "File_OpenStdio";
230 static SendPort newServicePort() native "File_NewServicePort";
521 231
522 static int checkedOpen(String name, int mode) { 232 static int checkedOpen(String name, int mode) {
523 if (name is !String || mode is !int) return 0; 233 if (name is !String || mode is !int) return 0;
524 return open(name, mode); 234 return open(name, mode);
525 } 235 }
526 236
527 static bool checkedCreate(String name) { 237 static bool checkedCreate(String name) {
528 if (name is !String) return false; 238 if (name is !String) return false;
529 return create(name); 239 return create(name);
530 } 240 }
(...skipping 18 matching lines...) Expand all
549 static int checkedWriteString(int id, String string) { 259 static int checkedWriteString(int id, String string) {
550 if (string is !String) return -1; 260 if (string is !String) return -1;
551 return writeString(id, string); 261 return writeString(id, string);
552 } 262 }
553 } 263 }
554 264
555 265
556 // Class for encapsulating the native implementation of files. 266 // Class for encapsulating the native implementation of files.
557 class _File implements File { 267 class _File implements File {
558 // Constructor for file. 268 // Constructor for file.
559 _File(String this._name) 269 _File(String this._name) : _asyncUsed = false;
560 : _scheduler = new _FileOperationScheduler(),
561 _asyncUsed = false;
562 270
563 void exists() { 271 void exists() {
272 _ensureFileService();
564 _asyncUsed = true; 273 _asyncUsed = true;
565 if (_name is !String) { 274 if (_name is !String) {
566 if (_errorHandler != null) { 275 if (_errorHandler != null) {
567 _errorHandler('File name is not a string: $_name'); 276 _errorHandler('File name is not a string: $_name');
568 } 277 }
569 return; 278 return;
570 } 279 }
571 var operation = new _ExistsOperation(_name); 280 List request = new List(2);
572 _scheduler.enqueue(operation, (result, ignored) { 281 request[0] = _FileUtils.kExistsRequest;
573 var handler = 282 request[1] = _name;
574 (_existsHandler != null) ? _existsHandler : (result) => null; 283 _fileService.call(request).receive((exists, replyTo) {
575 handler(result); 284 if (_existsHandler != null) _existsHandler(exists);
576 }); 285 });
577 } 286 }
578 287
579 bool existsSync() { 288 bool existsSync() {
580 if (_asyncUsed) { 289 if (_asyncUsed) {
581 throw new FileIOException( 290 throw new FileIOException(
582 "Mixed use of synchronous and asynchronous API"); 291 "Mixed use of synchronous and asynchronous API");
583 } 292 }
584 if (_name is !String) { 293 if (_name is !String) {
585 throw new FileIOException('File name is not a string: $_name'); 294 throw new FileIOException('File name is not a string: $_name');
586 } 295 }
587 return _FileUtils.exists(_name); 296 return _FileUtils.exists(_name);
588 } 297 }
589 298
590 void create() { 299 void create() {
300 _ensureFileService();
591 _asyncUsed = true; 301 _asyncUsed = true;
592 var handleCreateResult = (created, ignored) { 302 List request = new List(2);
593 var handler = (_createHandler != null) ? _createHandler : () => null; 303 request[0] = _FileUtils.kCreateRequest;
304 request[1] = _name;
305 _fileService.call(request).receive((created, replyTo) {
594 if (created) { 306 if (created) {
595 handler(); 307 if (_createHandler != null) _createHandler();
596 } else if (_errorHandler != null) { 308 } else if (_errorHandler != null) {
597 _errorHandler("Cannot create file: $_name"); 309 _errorHandler("Cannot create file: $_name");
598 } 310 }
599 }; 311 });
600 var operation = new _CreateOperation(_name);
601 _scheduler.enqueue(operation, handleCreateResult);
602 } 312 }
603 313
604 void createSync() { 314 void createSync() {
605 if (_asyncUsed) { 315 if (_asyncUsed) {
606 throw new FileIOException( 316 throw new FileIOException(
607 "Mixed use of synchronous and asynchronous API"); 317 "Mixed use of synchronous and asynchronous API");
608 } 318 }
609 bool created = _FileUtils.checkedCreate(_name); 319 bool created = _FileUtils.checkedCreate(_name);
610 if (!created) { 320 if (!created) {
611 throw new FileIOException("Cannot create file: $_name"); 321 throw new FileIOException("Cannot create file: $_name");
612 } 322 }
613 } 323 }
614 324
615 void delete() { 325 void delete() {
326 _ensureFileService();
616 _asyncUsed = true; 327 _asyncUsed = true;
617 var handleDeleteResult = (created, ignored) { 328 List request = new List(2);
618 var handler = (_deleteHandler != null) ? _deleteHandler : () => null; 329 request[0] = _FileUtils.kDeleteRequest;
619 if (created) { 330 request[1] = _name;
620 handler(); 331 _fileService.call(request).receive((deleted, replyTo) {
332 if (deleted) {
333 if (_deleteHandler != null) _deleteHandler();
621 } else if (_errorHandler != null) { 334 } else if (_errorHandler != null) {
622 _errorHandler("Cannot delete file: $_name"); 335 _errorHandler("Cannot delete file: $_name");
623 } 336 }
624 }; 337 });
625 var operation = new _DeleteOperation(_name);
626 _scheduler.enqueue(operation, handleDeleteResult);
627 } 338 }
628 339
629 void deleteSync() { 340 void deleteSync() {
630 if (_asyncUsed) { 341 if (_asyncUsed) {
631 throw new FileIOException( 342 throw new FileIOException(
632 "Mixed use of synchronous and asynchronous API"); 343 "Mixed use of synchronous and asynchronous API");
633 } 344 }
634 bool deleted = _FileUtils.checkedDelete(_name); 345 bool deleted = _FileUtils.checkedDelete(_name);
635 if (!deleted) { 346 if (!deleted) {
636 throw new FileIOException("Cannot delete file: $_name"); 347 throw new FileIOException("Cannot delete file: $_name");
637 } 348 }
638 } 349 }
639 350
640 void open([FileMode mode = FileMode.READ]) { 351 void open([FileMode mode = FileMode.READ]) {
352 _ensureFileService();
641 _asyncUsed = true; 353 _asyncUsed = true;
642 if (mode != FileMode.READ && 354 if (mode != FileMode.READ &&
643 mode != FileMode.WRITE && 355 mode != FileMode.WRITE &&
644 mode != FileMode.APPEND) { 356 mode != FileMode.APPEND) {
645 if (_errorHandler != null) { 357 if (_errorHandler != null) {
646 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " + 358 _errorHandler("Unknown file mode. Use FileMode.READ, FileMode.WRITE " +
647 "or FileMode.APPEND."); 359 "or FileMode.APPEND.");
648 return; 360 return;
649 } 361 }
650 } 362 }
651 var handleOpenResult = (id, ignored) { 363 List request = new List(3);
652 // If no open handler is present, close the file immediately to 364 request[0] = _FileUtils.kOpenRequest;
653 // avoid leaking an open file descriptor. 365 request[1] = _name;
366 request[2] = mode._mode; // Direct int value for serialization.
367 _fileService.call(request).receive((id, replyTo) {
654 var handler = _openHandler; 368 var handler = _openHandler;
655 if (handler === null) { 369 if (handler === null) {
370 // If no open handler is present, close the file immediately to
371 // avoid leaking an open file descriptor.
656 handler = (file) => file.close(); 372 handler = (file) => file.close();
657 } 373 }
658 if (id != 0) { 374 if (id != 0) {
659 var randomAccessFile = new _RandomAccessFile(id, _name); 375 var randomAccessFile = new _RandomAccessFile(id, _name);
660 handler(randomAccessFile); 376 handler(randomAccessFile);
661 } else if (_errorHandler != null) { 377 } else if (_errorHandler != null) {
662 _errorHandler("Cannot open file: $_name"); 378 _errorHandler("Cannot open file: $_name");
663 } 379 }
664 }; 380 });
665 var operation = new _OpenOperation(_name, mode._mode);
666 _scheduler.enqueue(operation, handleOpenResult);
667 } 381 }
668 382
669 RandomAccessFile openSync([FileMode mode = FileMode.READ]) { 383 RandomAccessFile openSync([FileMode mode = FileMode.READ]) {
670 if (_asyncUsed) { 384 if (_asyncUsed) {
671 throw new FileIOException( 385 throw new FileIOException(
672 "Mixed use of synchronous and asynchronous API"); 386 "Mixed use of synchronous and asynchronous API");
673 } 387 }
674 if (mode != FileMode.READ && 388 if (mode != FileMode.READ &&
675 mode != FileMode.WRITE && 389 mode != FileMode.WRITE &&
676 mode != FileMode.APPEND) { 390 mode != FileMode.APPEND) {
677 throw new FileIOException("Unknown file mode. Use FileMode.READ, " + 391 throw new FileIOException("Unknown file mode. Use FileMode.READ, " +
678 "FileMode.WRITE or FileMode.APPEND."); 392 "FileMode.WRITE or FileMode.APPEND.");
679 } 393 }
680 var id = _FileUtils.checkedOpen(_name, mode._mode); 394 var id = _FileUtils.checkedOpen(_name, mode._mode);
681 if (id == 0) { 395 if (id == 0) {
682 throw new FileIOException("Cannot open file: $_name"); 396 throw new FileIOException("Cannot open file: $_name");
683 } 397 }
684 return new _RandomAccessFile(id, _name); 398 return new _RandomAccessFile(id, _name);
685 } 399 }
686 400
687 static RandomAccessFile _openStdioSync(int fd) { 401 static RandomAccessFile _openStdioSync(int fd) {
688 var id = _FileUtils.openStdio(fd); 402 var id = _FileUtils.openStdio(fd);
689 if (id == 0) { 403 if (id == 0) {
690 throw new FileIOException("Cannot open stdio file for: $fd"); 404 throw new FileIOException("Cannot open stdio file for: $fd");
691 } 405 }
692 return new _RandomAccessFile(id, ""); 406 return new _RandomAccessFile(id, "");
693 } 407 }
694 408
695 void fullPath() { 409 void fullPath() {
410 _ensureFileService();
696 _asyncUsed = true; 411 _asyncUsed = true;
697 var handleFullPathResult = (result, ignored) { 412 List request = new List(2);
698 var handler = _fullPathHandler; 413 request[0] = _FileUtils.kFullPathRequest;
699 if (handler == null) handler = (path) => null; 414 request[1] = _name;
415 _fileService.call(request).receive((result, replyTo) {
700 if (result != null) { 416 if (result != null) {
701 handler(result); 417 if (_fullPathHandler != null) _fullPathHandler(result);
702 } else if (_errorHandler != null) { 418 } else if (_errorHandler != null) {
703 _errorHandler("fullPath failed"); 419 _errorHandler("fullPath failed");
704 } 420 }
705 }; 421 });
706 var operation = new _FullPathOperation(_name);
707 _scheduler.enqueue(operation, handleFullPathResult);
708 } 422 }
709 423
710 String fullPathSync() { 424 String fullPathSync() {
711 if (_asyncUsed) { 425 if (_asyncUsed) {
712 throw new FileIOException( 426 throw new FileIOException(
713 "Mixed use of synchronous and asynchronous API"); 427 "Mixed use of synchronous and asynchronous API");
714 } 428 }
715 String result = _FileUtils.checkedFullPath(_name); 429 String result = _FileUtils.checkedFullPath(_name);
716 if (result == null) { 430 if (result == null) {
717 throw new FileIOException("fullPath failed"); 431 throw new FileIOException("fullPath failed");
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 } 523 }
810 524
811 void set fullPathHandler(void handler(String)) { 525 void set fullPathHandler(void handler(String)) {
812 _fullPathHandler = handler; 526 _fullPathHandler = handler;
813 } 527 }
814 528
815 void set errorHandler(void handler(String error)) { 529 void set errorHandler(void handler(String error)) {
816 _errorHandler = handler; 530 _errorHandler = handler;
817 } 531 }
818 532
533 void _ensureFileService() {
534 if (_fileService == null) {
535 _fileService = _FileUtils.newServicePort();
536 }
537 }
538
819 String _name; 539 String _name;
820 bool _asyncUsed; 540 bool _asyncUsed;
821 541
822 _FileOperationScheduler _scheduler; 542 SendPort _fileService;
823 543
824 Function _existsHandler; 544 Function _existsHandler;
825 Function _createHandler; 545 Function _createHandler;
826 Function _deleteHandler; 546 Function _deleteHandler;
827 Function _openHandler; 547 Function _openHandler;
828 Function _inputStreamHandler; 548 Function _inputStreamHandler;
829 Function _outputStreamHandler; 549 Function _outputStreamHandler;
830 Function _fullPathHandler; 550 Function _fullPathHandler;
831 Function _errorHandler; 551 Function _errorHandler;
832 } 552 }
833 553
834 554
835 class _RandomAccessFile implements RandomAccessFile { 555 class _RandomAccessFile implements RandomAccessFile {
836 _RandomAccessFile(int this._id, String this._name) 556 _RandomAccessFile(int this._id, String this._name) : _asyncUsed = false;
837 : _scheduler = new _FileOperationScheduler(),
838 _asyncUsed = false;
839 557
840 void close() { 558 void close() {
559 if (_id == 0) return;
560 _ensureFileService();
841 _asyncUsed = true; 561 _asyncUsed = true;
842 var handleCloseResult = (result, ignored) { 562 List request = new List(2);
843 var handler = (_closeHandler != null) ? _closeHandler : () => null; 563 request[0] = _FileUtils.kCloseRequest;
564 request[1] = _id;
565 // Set the id_ to 0 (NULL) to ensure the no more async requests
566 // can be issues for this file.
567 _id = 0;
568 _fileService.call(request).receive((result, replyTo) {
844 if (result != -1) { 569 if (result != -1) {
845 _id = result; 570 _id = result;
846 handler(); 571 if (_closeHandler != null) _closeHandler();
847 } else if (_errorHandler != null) { 572 } else if (_errorHandler != null) {
848 _errorHandler("Cannot close file: $_name"); 573 _errorHandler("Cannot close file: $_name");
849 } 574 }
850 }; 575 });
851 var operation = new _CloseOperation(_id);
852 _scheduler.enqueue(operation, handleCloseResult);
853 } 576 }
854 577
855 void closeSync() { 578 void closeSync() {
856 if (_asyncUsed) { 579 if (_asyncUsed) {
857 throw new FileIOException( 580 throw new FileIOException(
858 "Mixed use of synchronous and asynchronous API"); 581 "Mixed use of synchronous and asynchronous API");
859 } 582 }
860 var id = _FileUtils.close(_id); 583 var id = _FileUtils.close(_id);
861 if (id == -1) { 584 if (id == -1) {
862 throw new FileIOException("Cannot close file: $_name"); 585 throw new FileIOException("Cannot close file: $_name");
863 } 586 }
864 _id = id; 587 _id = id;
865 } 588 }
866 589
867 void readByte() { 590 void readByte() {
591 _ensureFileService();
868 _asyncUsed = true; 592 _asyncUsed = true;
869 var handleReadByteResult = (result, ignored) { 593 List request = new List(2);
870 var handler = 594 request[0] = _FileUtils.kReadByteRequest;
871 (_readByteHandler != null) ? _readByteHandler : (byte) => null; 595 request[1] = _id;
596 _fileService.call(request).receive((result, replyTo) {
872 if (result != -1) { 597 if (result != -1) {
873 handler(result); 598 if (_readByteHandler != null) _readByteHandler(result);
874 } else if (_errorHandler != null) { 599 } else if (_errorHandler != null) {
875 _errorHandler("readByte failed"); 600 _errorHandler("readByte failed");
876 } 601 }
877 }; 602 });
878 var operation = new _ReadByteOperation(_id);
879 _scheduler.enqueue(operation, handleReadByteResult);
880 } 603 }
881 604
882 int readByteSync() { 605 int readByteSync() {
883 if (_asyncUsed) { 606 if (_asyncUsed) {
884 throw new FileIOException( 607 throw new FileIOException(
885 "Mixed use of synchronous and asynchronous API"); 608 "Mixed use of synchronous and asynchronous API");
886 } 609 }
887 int result = _FileUtils.readByte(_id); 610 int result = _FileUtils.readByte(_id);
888 if (result == -1) { 611 if (result == -1) {
889 throw new FileIOException("readByte failed"); 612 throw new FileIOException("readByte failed");
890 } 613 }
891 return result; 614 return result;
892 } 615 }
893 616
894 void readList(List<int> buffer, int offset, int bytes) { 617 void readList(List<int> buffer, int offset, int bytes) {
618 _ensureFileService();
895 _asyncUsed = true; 619 _asyncUsed = true;
896 if (buffer is !List || offset is !int || bytes is !int) { 620 if (buffer is !List || offset is !int || bytes is !int) {
897 if (_errorHandler != null) { 621 if (_errorHandler != null) {
898 _errorHandler("Invalid arguments to readList"); 622 _errorHandler("Invalid arguments to readList");
899 } 623 }
900 return; 624 return;
901 }; 625 };
902 var handleReadListResult = (result, ignored) { 626 List request = new List(3);
903 var handler = 627 request[0] = _FileUtils.kReadListRequest;
904 (_readListHandler != null) ? _readListHandler : (result) => null; 628 request[1] = _id;
905 if (result is _ReadListResult && result.read != -1) { 629 request[2] = bytes;
906 var read = result.read; 630 _fileService.call(request).receive((result, replyTo) {
907 buffer.setRange(offset, read, result.buffer); 631 if (result is List && result.length == 2 && result[0] != -1) {
908 handler(read); 632 var read = result[0];
633 var data = result[1];
634 buffer.setRange(offset, read, data);
635 if (_readListHandler != null) _readListHandler(read);
909 return; 636 return;
910 } 637 } else if (_errorHandler != null) {
911 if (_errorHandler != null) {
912 _errorHandler(result is String ? result : "readList failed"); 638 _errorHandler(result is String ? result : "readList failed");
913 } 639 }
914 }; 640 });
915 var operation = new _ReadListOperation(_id, buffer.length, offset, bytes);
916 _scheduler.enqueue(operation, handleReadListResult);
917 } 641 }
918 642
919 int readListSync(List<int> buffer, int offset, int bytes) { 643 int readListSync(List<int> buffer, int offset, int bytes) {
920 if (_asyncUsed) { 644 if (_asyncUsed) {
921 throw new FileIOException( 645 throw new FileIOException(
922 "Mixed use of synchronous and asynchronous API"); 646 "Mixed use of synchronous and asynchronous API");
923 } 647 }
924 if (buffer is !List || offset is !int || bytes is !int) { 648 if (buffer is !List || offset is !int || bytes is !int) {
925 throw new FileIOException("Invalid arguments to readList"); 649 throw new FileIOException("Invalid arguments to readList");
926 } 650 }
927 if (bytes == 0) return 0; 651 if (bytes == 0) return 0;
928 int index = 652 int index =
929 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); 653 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes);
930 if (index != 0) { 654 if (index != 0) {
931 throw new IndexOutOfRangeException(index); 655 throw new IndexOutOfRangeException(index);
932 } 656 }
933 int result = _FileUtils.readList(_id, buffer, offset, bytes); 657 int result = _FileUtils.readList(_id, buffer, offset, bytes);
934 if (result == -1) { 658 if (result == -1) {
935 throw new FileIOException("readList failed"); 659 throw new FileIOException("readList failed");
936 } 660 }
937 return result; 661 return result;
938 } 662 }
939 663
940 void _checkPendingWrites() {
941 if (_scheduler.noPendingWrite() && _noPendingWriteHandler != null) {
942 _noPendingWriteHandler();
943 }
944 }
945
946 void writeByte(int value) { 664 void writeByte(int value) {
665 _ensureFileService();
947 _asyncUsed = true; 666 _asyncUsed = true;
948 if (value is !int) { 667 if (value is !int) {
949 if (_errorHandler != null) { 668 if (_errorHandler != null) {
950 _errorHandler("Invalid argument to writeByte"); 669 _errorHandler("Invalid argument to writeByte");
951 } 670 }
952 return; 671 return;
953 } 672 }
954 var handleReadByteResult = (result, ignored) { 673 List request = new List(3);
955 if (result == -1 &&_errorHandler != null) { 674 request[0] = _FileUtils.kWriteByteRequest;
675 request[1] = _id;
676 request[2] = value;
677 _writeEnqueued();
678 _fileService.call(request).receive((result, replyTo) {
679 _writesCompleted();
680 if (result == -1 && _errorHandler !== null) {
956 _errorHandler("writeByte failed"); 681 _errorHandler("writeByte failed");
957 return;
958 } 682 }
959 _checkPendingWrites(); 683 });
960 };
961 var operation = new _WriteByteOperation(_id, value);
962 _scheduler.enqueue(operation, handleReadByteResult);
963 } 684 }
964 685
965 int writeByteSync(int value) { 686 int writeByteSync(int value) {
966 if (_asyncUsed) { 687 if (_asyncUsed) {
967 throw new FileIOException( 688 throw new FileIOException(
968 "Mixed use of synchronous and asynchronous API"); 689 "Mixed use of synchronous and asynchronous API");
969 } 690 }
970 if (value is !int) { 691 if (value is !int) {
971 throw new FileIOException("Invalid argument to writeByte"); 692 throw new FileIOException("Invalid argument to writeByte");
972 } 693 }
973 int result = _FileUtils.writeByte(_id, value); 694 int result = _FileUtils.writeByte(_id, value);
974 if (result == -1) { 695 if (result == -1) {
975 throw new FileIOException("writeByte failed"); 696 throw new FileIOException("writeByte failed");
976 } 697 }
977 return result; 698 return result;
978 } 699 }
979 700
980 void writeList(List<int> buffer, int offset, int bytes) { 701 void writeList(List<int> buffer, int offset, int bytes) {
702 _ensureFileService();
981 _asyncUsed = true; 703 _asyncUsed = true;
982 if (buffer is !List || offset is !int || bytes is !int) { 704 if (buffer is !List || offset is !int || bytes is !int) {
983 if (_errorHandler != null) { 705 if (_errorHandler != null) {
984 _errorHandler("Invalid arguments to writeList"); 706 _errorHandler("Invalid arguments to writeList");
985 } 707 }
986 return; 708 return;
987 } 709 }
988 var handleWriteListResult = (result, ignored) { 710
989 if (result is !String && result != -1) { 711 List result =
990 if (result < bytes) { 712 _FileUtils.ensureFastAndSerializabelBuffer(buffer, offset, bytes);
991 writeList(buffer, offset + result, bytes - result); 713 List outBuffer = result[0];
992 } else { 714 int outOffset = result[1];
993 _checkPendingWrites(); 715
994 } 716 List request = new List(5);
995 return; 717 request[0] = _FileUtils.kWriteListRequest;
718 request[1] = _id;
719 request[2] = outBuffer;
720 request[3] = outOffset;
721 request[4] = bytes;
722 _writeEnqueued();
723 _fileService.call(request).receive((result, replyTo) {
724 _writesCompleted();
725 if (result == -1 && _errorHandler !== null) {
726 _errorHandler("writeList failed");
996 } 727 }
997 if (_errorHandler != null) { 728 });
998 _errorHandler(result is String ? result : "writeList failed");
999 }
1000 };
1001 var operation = new _WriteListOperation(_id, buffer, offset, bytes);
1002 _scheduler.enqueue(operation, handleWriteListResult);
1003 } 729 }
1004 730
1005 int writeListSync(List<int> buffer, int offset, int bytes) { 731 int writeListSync(List<int> buffer, int offset, int bytes) {
1006 if (_asyncUsed) { 732 if (_asyncUsed) {
1007 throw new FileIOException( 733 throw new FileIOException(
1008 "Mixed use of synchronous and asynchronous API"); 734 "Mixed use of synchronous and asynchronous API");
1009 } 735 }
1010 if (buffer is !List || offset is !int || bytes is !int) { 736 if (buffer is !List || offset is !int || bytes is !int) {
1011 throw new FileIOException("Invalid arguments to writeList"); 737 throw new FileIOException("Invalid arguments to writeList");
1012 } 738 }
1013 if (bytes == 0) return 0; 739 if (bytes == 0) return 0;
1014 int index = 740 int index =
1015 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes); 741 _FileUtils.checkReadWriteListArguments(buffer.length, offset, bytes);
1016 if (index != 0) { 742 if (index != 0) {
1017 throw new IndexOutOfRangeException(index); 743 throw new IndexOutOfRangeException(index);
1018 } 744 }
1019 int result = _FileUtils.writeList(_id, buffer, offset, bytes); 745 int result = _FileUtils.writeList(_id, buffer, offset, bytes);
1020 if (result == -1) { 746 if (result == -1) {
1021 throw new FileIOException("writeList failed"); 747 throw new FileIOException("writeList failed");
1022 } 748 }
1023 return result; 749 return result;
1024 } 750 }
1025 751
1026 void writeString(String string) { 752 void writeString(String string) {
753 _ensureFileService();
1027 _asyncUsed = true; 754 _asyncUsed = true;
1028 var handleWriteStringResult = (result, ignored) { 755 List request = new List(3);
1029 if (result == -1 &&_errorHandler != null) { 756 request[0] = _FileUtils.kWriteStringRequest;
757 request[1] = _id;
758 request[2] = string;
759 _writeEnqueued();
760 _fileService.call(request).receive((result, replyTo) {
761 _writesCompleted();
762 if (result == -1 && _errorHandler !== null) {
1030 _errorHandler("writeString failed"); 763 _errorHandler("writeString failed");
1031 return;
1032 } 764 }
1033 if (result < string.length) { 765 });
1034 writeString(string.substring(result));
1035 } else {
1036 _checkPendingWrites();
1037 }
1038 };
1039 var operation = new _WriteStringOperation(_id, string);
1040 _scheduler.enqueue(operation, handleWriteStringResult);
1041 } 766 }
1042 767
1043 int writeStringSync(String string) { 768 int writeStringSync(String string) {
1044 if (_asyncUsed) { 769 if (_asyncUsed) {
1045 throw new FileIOException( 770 throw new FileIOException(
1046 "Mixed use of synchronous and asynchronous API"); 771 "Mixed use of synchronous and asynchronous API");
1047 } 772 }
1048 int result = _FileUtils.checkedWriteString(_id, string); 773 int result = _FileUtils.checkedWriteString(_id, string);
1049 if (result == -1) { 774 if (result == -1) {
1050 throw new FileIOException("writeString failed"); 775 throw new FileIOException("writeString failed");
1051 } 776 }
1052 return result; 777 return result;
1053 } 778 }
1054 779
1055 void position() { 780 void position() {
781 _ensureFileService();
1056 _asyncUsed = true; 782 _asyncUsed = true;
1057 var handlePositionResult = (result, ignored) { 783 List request = new List(2);
1058 var handler = 784 request[0] = _FileUtils.kPositionRequest;
1059 (_positionHandler != null) ? _positionHandler : (pos) => null; 785 request[1] = _id;
1060 if (result == -1 && _errorHandler != null) { 786 _fileService.call(request).receive((result, replyTo) {
787 if (result != -1) {
788 if (_positionHandler != null) _positionHandler(result);
789 } else if (_errorHandler != null) {
1061 _errorHandler("position failed"); 790 _errorHandler("position failed");
1062 return;
1063 } 791 }
1064 handler(result); 792 });
1065 };
1066 var operation = new _PositionOperation(_id);
1067 _scheduler.enqueue(operation, handlePositionResult);
1068 } 793 }
1069 794
1070 int positionSync() { 795 int positionSync() {
1071 if (_asyncUsed) { 796 if (_asyncUsed) {
1072 throw new FileIOException( 797 throw new FileIOException(
1073 "Mixed use of synchronous and asynchronous API"); 798 "Mixed use of synchronous and asynchronous API");
1074 } 799 }
1075 int result = _FileUtils.position(_id); 800 int result = _FileUtils.position(_id);
1076 if (result == -1) { 801 if (result == -1) {
1077 throw new FileIOException("position failed"); 802 throw new FileIOException("position failed");
1078 } 803 }
1079 return result; 804 return result;
1080 } 805 }
1081 806
1082 void setPosition(int position) { 807 void setPosition(int position) {
808 _ensureFileService();
1083 _asyncUsed = true; 809 _asyncUsed = true;
1084 var handleSetPositionResult = (result, ignored) { 810 List request = new List(3);
1085 var handler = 811 request[0] = _FileUtils.kSetPositionRequest;
1086 (_setPositionHandler != null) ? _setPositionHandler : () => null; 812 request[1] = _id;
1087 if (result == false && _errorHandler != null) { 813 request[2] = position;
814 _fileService.call(request).receive((result, replyTo) {
815 if (result) {
816 if (_setPositionHandler != null) _setPositionHandler();
817 } else if (_errorHandler != null) {
1088 _errorHandler("setPosition failed"); 818 _errorHandler("setPosition failed");
1089 return;
1090 } 819 }
1091 handler(); 820 });
1092 };
1093 var operation = new _SetPositionOperation(_id, position);
1094 _scheduler.enqueue(operation, handleSetPositionResult);
1095 } 821 }
1096 822
1097 void setPositionSync(int position) { 823 void setPositionSync(int position) {
824 _ensureFileService();
1098 if (_asyncUsed) { 825 if (_asyncUsed) {
1099 throw new FileIOException( 826 throw new FileIOException(
1100 "Mixed use of synchronous and asynchronous API"); 827 "Mixed use of synchronous and asynchronous API");
1101 } 828 }
1102 bool result = _FileUtils.setPosition(_id, position); 829 bool result = _FileUtils.setPosition(_id, position);
1103 if (result == false) { 830 if (result == false) {
1104 throw new FileIOException("setPosition failed"); 831 throw new FileIOException("setPosition failed");
1105 } 832 }
1106 } 833 }
1107 834
1108 void truncate(int length) { 835 void truncate(int length) {
836 _ensureFileService();
1109 _asyncUsed = true; 837 _asyncUsed = true;
1110 var handleTruncateResult = (result, ignored) { 838 List request = new List(3);
1111 var handler = (_truncateHandler != null) ? _truncateHandler : () => null; 839 request[0] = _FileUtils.kTruncateRequest;
1112 if (result == false && _errorHandler != null) { 840 request[1] = _id;
841 request[2] = length;
842 _fileService.call(request).receive((result, replyTo) {
843 if (result) {
844 if (_truncateHandler != null) _truncateHandler();
845 } else if (_errorHandler != null) {
1113 _errorHandler("truncate failed"); 846 _errorHandler("truncate failed");
1114 return;
1115 } 847 }
1116 handler(); 848 });
1117 };
1118 var operation = new _TruncateOperation(_id, length);
1119 _scheduler.enqueue(operation, handleTruncateResult);
1120 } 849 }
1121 850
1122 void truncateSync(int length) { 851 void truncateSync(int length) {
1123 if (_asyncUsed) { 852 if (_asyncUsed) {
1124 throw new FileIOException( 853 throw new FileIOException(
1125 "Mixed use of synchronous and asynchronous API"); 854 "Mixed use of synchronous and asynchronous API");
1126 } 855 }
1127 bool result = _FileUtils.truncate(_id, length); 856 bool result = _FileUtils.truncate(_id, length);
1128 if (result == false) { 857 if (result == false) {
1129 throw new FileIOException("truncate failed"); 858 throw new FileIOException("truncate failed");
1130 } 859 }
1131 } 860 }
1132 861
1133 void length() { 862 void length() {
863 _ensureFileService();
1134 _asyncUsed = true; 864 _asyncUsed = true;
1135 var handleLengthResult = (result, ignored) { 865 List request = new List(2);
1136 var handler = (_lengthHandler != null) ? _lengthHandler : (pos) => null; 866 request[0] = _FileUtils.kLengthRequest;
1137 if (result == -1 && _errorHandler != null) { 867 request[1] = _id;
868 _fileService.call(request).receive((result, replyTo) {
869 if (result != -1) {
870 if (_lengthHandler != null) _lengthHandler(result);
871 } else if (_errorHandler != null) {
1138 _errorHandler("length failed"); 872 _errorHandler("length failed");
1139 return;
1140 } 873 }
1141 handler(result); 874 });
1142 };
1143 var operation = new _LengthOperation(_id);
1144 _scheduler.enqueue(operation, handleLengthResult);
1145 } 875 }
1146 876
1147 int lengthSync() { 877 int lengthSync() {
1148 if (_asyncUsed) { 878 if (_asyncUsed) {
1149 throw new FileIOException( 879 throw new FileIOException(
1150 "Mixed use of synchronous and asynchronous API"); 880 "Mixed use of synchronous and asynchronous API");
1151 } 881 }
1152 int result = _FileUtils.length(_id); 882 int result = _FileUtils.length(_id);
1153 if (result == -1) { 883 if (result == -1) {
1154 throw new FileIOException("length failed"); 884 throw new FileIOException("length failed");
1155 } 885 }
1156 return result; 886 return result;
1157 } 887 }
1158 888
1159 void flush() { 889 void flush() {
890 _ensureFileService();
1160 _asyncUsed = true; 891 _asyncUsed = true;
1161 var handleFlushResult = (result, ignored) { 892 List request = new List(2);
1162 var handler = (_flushHandler != null) ? _flushHandler : (pos) => null; 893 request[0] = _FileUtils.kFlushRequest;
1163 if (result == -1 && _errorHandler != null) { 894 request[1] = _id;
895 _fileService.call(request).receive((result, replyTo) {
896 if (result != -1) {
897 if (_flushHandler != null) _flushHandler();
898 } else if (_errorHandler != null) {
1164 _errorHandler("flush failed"); 899 _errorHandler("flush failed");
1165 return;
1166 } 900 }
1167 handler(); 901 });
1168 };
1169 var operation = new _FlushOperation(_id);
1170 _scheduler.enqueue(operation, handleFlushResult);
1171 } 902 }
1172 903
1173 void flushSync() { 904 void flushSync() {
1174 if (_asyncUsed) { 905 if (_asyncUsed) {
1175 throw new FileIOException( 906 throw new FileIOException(
1176 "Mixed use of synchronous and asynchronous API"); 907 "Mixed use of synchronous and asynchronous API");
1177 } 908 }
1178 int result = _FileUtils.flush(_id); 909 int result = _FileUtils.flush(_id);
1179 if (result == -1) { 910 if (result == -1) {
1180 throw new FileIOException("flush failed"); 911 throw new FileIOException("flush failed");
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 } 947 }
1217 948
1218 void set lengthHandler(void handler(int length)) { 949 void set lengthHandler(void handler(int length)) {
1219 _lengthHandler = handler; 950 _lengthHandler = handler;
1220 } 951 }
1221 952
1222 void set flushHandler(void handler()) { 953 void set flushHandler(void handler()) {
1223 _flushHandler = handler; 954 _flushHandler = handler;
1224 } 955 }
1225 956
957 void _ensureFileService() {
958 if (_fileService == null) {
959 _fileService = _FileUtils.newServicePort();
960 }
961 }
962
963 void _writeEnqueued() => _pendingWrites++;
964
965 void _writesCompleted() {
Mads Ager (google) 2012/02/23 08:57:44 writes -> write
Søren Gjesse 2012/02/23 10:26:42 Done.
966 _pendingWrites--;
967 if (_pendingWrites == 0 && _noPendingWriteHandler != null) {
968 _noPendingWriteHandler();
969 }
970 }
971
972
1226 String _name; 973 String _name;
1227 int _id; 974 int _id;
1228 bool _asyncUsed; 975 bool _asyncUsed;
976 int _pendingWrites = 0;
1229 977
1230 _FileOperationScheduler _scheduler; 978 SendPort _fileService;
1231 979
1232 Function _closeHandler; 980 Function _closeHandler;
1233 Function _readByteHandler; 981 Function _readByteHandler;
1234 Function _readListHandler; 982 Function _readListHandler;
1235 Function _noPendingWriteHandler; 983 Function _noPendingWriteHandler;
1236 Function _positionHandler; 984 Function _positionHandler;
1237 Function _setPositionHandler; 985 Function _setPositionHandler;
1238 Function _truncateHandler; 986 Function _truncateHandler;
1239 Function _lengthHandler; 987 Function _lengthHandler;
1240 Function _flushHandler; 988 Function _flushHandler;
1241 Function _errorHandler; 989 Function _errorHandler;
1242 } 990 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698