Index: sdk/lib/io/directory_impl.dart |
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart |
index 620437c0e288d246ed29004d4de0429fe43a71fb..d76b86d83988a29832475e51735a738733f44390 100644 |
--- a/sdk/lib/io/directory_impl.dart |
+++ b/sdk/lib/io/directory_impl.dart |
@@ -252,6 +252,12 @@ class _Directory extends FileSystemEntity implements Directory { |
} |
} |
+abstract class _AsyncDirectoryListerOps { |
+ external factory _AsyncDirectoryListerOps(int pointer); |
+ |
+ int getPointer(); |
+} |
+ |
class _AsyncDirectoryLister { |
static const int LIST_FILE = 0; |
static const int LIST_DIRECTORY = 1; |
@@ -269,10 +275,10 @@ class _AsyncDirectoryLister { |
final bool followLinks; |
StreamController controller; |
- int id; |
bool canceled = false; |
bool nextRunning = false; |
bool closed = false; |
+ _AsyncDirectoryListerOps _ops; |
Completer closeCompleter = new Completer(); |
_AsyncDirectoryLister(this.path, this.recursive, this.followLinks) { |
@@ -282,13 +288,21 @@ class _AsyncDirectoryLister { |
sync: true); |
} |
+ // Calling this function will increase the reference count on the native |
+ // object that implements the async directory lister operations. It should |
+ // only be called to pass the pointer to the IO Service, which will decrement |
+ // the reference count when it is finished with it. |
+ int _pointer() { |
+ return (_ops == null) ? null : _ops.getPointer(); |
+ } |
+ |
Stream get stream => controller.stream; |
void onListen() { |
_IOService._dispatch(_DIRECTORY_LIST_START, [path, recursive, followLinks]) |
.then((response) { |
if (response is int) { |
- id = response; |
+ _ops = new _AsyncDirectoryListerOps(response); |
next(); |
} else if (response is Error) { |
controller.addError(response, response.stackTrace); |
@@ -301,7 +315,9 @@ class _AsyncDirectoryLister { |
} |
void onResume() { |
- if (!nextRunning) next(); |
+ if (!nextRunning) { |
+ next(); |
+ } |
} |
Future onCancel() { |
@@ -319,11 +335,15 @@ class _AsyncDirectoryLister { |
close(); |
return; |
} |
- if (id == null) return; |
- if (controller.isPaused) return; |
- if (nextRunning) return; |
+ if (controller.isPaused || nextRunning) { |
+ return; |
+ } |
+ var pointer = _pointer(); |
+ if (pointer == null) { |
+ return; |
+ } |
nextRunning = true; |
- _IOService._dispatch(_DIRECTORY_LIST_NEXT, [id]).then((result) { |
+ _IOService._dispatch(_DIRECTORY_LIST_NEXT, [pointer]).then((result) { |
nextRunning = false; |
if (result is List) { |
next(); |
@@ -354,18 +374,27 @@ class _AsyncDirectoryLister { |
}); |
} |
+ void _cleanup() { |
+ controller.close(); |
+ closeCompleter.complete(); |
+ _ops = null; |
+ } |
+ |
void close() { |
- if (closed) return; |
- if (nextRunning) return; |
- void cleanup() { |
- controller.close(); |
- closeCompleter.complete(); |
+ if (closed) { |
+ return; |
+ } |
+ if (nextRunning) { |
+ return; |
} |
closed = true; |
- if (id != null) { |
- _IOService._dispatch(_DIRECTORY_LIST_STOP, [id]).whenComplete(cleanup); |
+ |
+ var pointer = _pointer(); |
+ if (pointer == null) { |
+ _cleanup(); |
} else { |
- cleanup(); |
+ _IOService._dispatch(_DIRECTORY_LIST_STOP, [pointer]) |
+ .whenComplete(_cleanup); |
} |
} |