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

Side by Side Diff: utils/archive/input_stream.dart

Issue 10825139: Free the C memory for ArchiveInputStream when the stream is garbage collected. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix a renamed function Created 8 years, 4 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
« no previous file with comments | « utils/archive/dart_archive.c ('k') | utils/archive/reader.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #library("input_stream"); 5 #library("input_stream");
6 6
7 #import("entry.dart"); 7 #import("entry.dart");
8 #import("read_request.dart"); 8 #import("read_request.dart");
9 #import("utils.dart"); 9 #import("utils.dart");
10 10
11 // TODO(nweiz): ensure that the C struct associated with an input stream gets
12 // freed if the stream gets garbage collected before it's closed.
13 /** 11 /**
14 * A stream of [ArchiveEntry]s being read from an archive. 12 * A stream of [ArchiveEntry]s being read from an archive.
15 * 13 *
16 * This is accessible via [ArchiveReader]. 14 * This is accessible via [ArchiveReader].
17 */ 15 */
18 class ArchiveInputStream { 16 class ArchiveInputStream {
19 /** 17 /**
20 * The id of the underlying archive. 18 * The id of the underlying archive.
21 * 19 *
22 * This will be set to null once the input stream has finished reading from 20 * This will be set to null once the input stream has finished reading from
23 * the archive. 21 * the archive.
24 */ 22 */
25 int _id; 23 final Reference<int> _id;
26 24
27 /** A [Completer] that will fire once the [_onEntry] callback is set. */ 25 /** A [Completer] that will fire once the [_onEntry] callback is set. */
28 final Completer<Function> _onEntryCompleter; 26 final Completer<Function> _onEntryCompleter;
29 27
30 /** The callback to call when the input stream is closed. */ 28 /** The callback to call when the input stream is closed. */
31 Function _onClosed; 29 Function _onClosed;
32 30
33 /** The callback to call when an error occurs. */ 31 /** The callback to call when an error occurs. */
34 Function _onError; 32 Function _onError;
35 33
36 /** The entry that is currently eligible to read data from the archive. */ 34 /** The entry that is currently eligible to read data from the archive. */
37 ArchiveEntry _currentEntry; 35 ArchiveEntry _currentEntry;
38 36
39 ArchiveInputStream(this._id) : _onEntryCompleter = new Completer<Function>() { 37 ArchiveInputStream(int id) : _id = new Reference<int>(id),
Bob Nystrom 2012/08/01 23:52:36 How about moving : to the next line and not indent
38 _onEntryCompleter = new Completer<Function>() {
40 var future = _consumeHeaders(); 39 var future = _consumeHeaders();
41 future.handleException((e) { 40 future.handleException((e) {
42 if (_onError != null) { 41 if (_onError != null) {
43 _onError(e, future.stackTrace); 42 _onError(e, future.stackTrace);
44 return true; 43 return true;
45 } else { 44 } else {
46 throw e; 45 throw e;
47 } 46 }
48 }); 47 });
49 48
50 future.then((_) { 49 future.then((_) {
51 close(); 50 close();
52 if (_onClosed != null) _onClosed(); 51 if (_onClosed != null) _onClosed();
53 }); 52 });
53
54 attachFinalizer(this, (id) {
55 if (id.value != null) call(FREE, id.value).then(() {});
56 }, _id);
54 } 57 }
55 58
56 /** Whether this stream has finished reading entries. */ 59 /** Whether this stream has finished reading entries. */
57 bool get closed() => _id == null; 60 bool get closed() => _id.value == null;
58 61
59 /** 62 /**
60 * Sets a callback to call when a new entry is read from the archive. 63 * Sets a callback to call when a new entry is read from the archive.
61 * 64 *
62 * The [ArchiveEntry] that's read from an archive initially only contains 65 * The [ArchiveEntry] that's read from an archive initially only contains
63 * header information such as the filename and permissions. To get the actual 66 * header information such as the filename and permissions. To get the actual
64 * data contained in the entry, use [ArchiveEntry.openInputStream]. 67 * data contained in the entry, use [ArchiveEntry.openInputStream].
65 * 68 *
66 * Since the entries are read in sequence from the archive, the data stream 69 * Since the entries are read in sequence from the archive, the data stream
67 * for one entry must be opened before the next entry is read from the 70 * for one entry must be opened before the next entry is read from the
(...skipping 21 matching lines...) Expand all
89 */ 92 */
90 void set onError(void callback(e, stack)) { 93 void set onError(void callback(e, stack)) {
91 _onError = callback; 94 _onError = callback;
92 } 95 }
93 96
94 /** 97 /**
95 * Closes the input stream. No more entries will be emitted. 98 * Closes the input stream. No more entries will be emitted.
96 */ 99 */
97 void close() { 100 void close() {
98 if (closed) return; 101 if (closed) return;
99 call(FREE, _id).then((_) {}); 102 call(FREE, _id.value).then((_) {});
100 _id = null; 103 _id.value = null;
101 if (_currentEntry != null) _currentEntry.close(); 104 if (_currentEntry != null) _currentEntry.close();
102 if (!_onEntryCompleter.future.isComplete) _onEntryCompleter.complete(null); 105 if (!_onEntryCompleter.future.isComplete) _onEntryCompleter.complete(null);
103 } 106 }
104 107
105 /** 108 /**
106 * Consumes and emits all [ArchiveEntries] in this archive. 109 * Consumes and emits all [ArchiveEntries] in this archive.
107 */ 110 */
108 Future _consumeHeaders() { 111 Future _consumeHeaders() {
109 if (closed) return new Future.immediate(null); 112 if (closed) return new Future.immediate(null);
110 var data; 113 var data;
111 return call(NEXT_HEADER, _id).chain((_data) { 114 return call(NEXT_HEADER, _id.value).chain((_data) {
112 data = _data; 115 data = _data;
113 if (data == null) return new Future.immediate(null); 116 if (data == null) return new Future.immediate(null);
114 return _emit(new ArchiveEntry(_id, data)). 117 return _emit(new ArchiveEntry(_id.value, data)).
115 chain((_) => _consumeHeaders()); 118 chain((_) => _consumeHeaders());
116 }); 119 });
117 } 120 }
118 121
119 /** 122 /**
120 * Emits [entry] to the [onEntry] callback. Returns a [Future] that will 123 * Emits [entry] to the [onEntry] callback. Returns a [Future] that will
121 * complete once the callback's return value completes and the entry's data 124 * complete once the callback's return value completes and the entry's data
122 * has been fully consumed. 125 * has been fully consumed.
123 */ 126 */
124 Future _emit(ArchiveEntry entry) { 127 Future _emit(ArchiveEntry entry) {
125 _currentEntry = entry; 128 _currentEntry = entry;
126 var future = _onEntryCompleter.future.chain((onEntry) { 129 var future = _onEntryCompleter.future.chain((onEntry) {
127 if (closed) return new Future.immediate(null); 130 if (closed) return new Future.immediate(null);
128 var result = onEntry(entry); 131 var result = onEntry(entry);
129 if (result is Future) return result; 132 if (result is Future) return result;
130 return new Future.immediate(null); 133 return new Future.immediate(null);
131 }).chain((_) { 134 }).chain((_) {
132 if (entry.isInputOpen) return entry.inputComplete; 135 if (entry.isInputOpen) return entry.inputComplete;
133 return new Future.immediate(null); 136 return new Future.immediate(null);
134 }); 137 });
135 future.onComplete((_) { 138 future.onComplete((_) {
136 _currentEntry = null; 139 _currentEntry = null;
137 entry.close(); 140 entry.close();
138 }); 141 });
139 return future; 142 return future;
140 } 143 }
141 } 144 }
OLDNEW
« no previous file with comments | « utils/archive/dart_archive.c ('k') | utils/archive/reader.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698