OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 part of core; | 5 part of core; |
6 | 6 |
7 class _MojoHandleNatives { | 7 class _MojoHandleNatives { |
8 static int register(MojoEventStream eventStream) native "MojoHandle_Register"; | 8 static int register(MojoEventStream eventStream) native "MojoHandle_Register"; |
9 static int close(int handle) native "MojoHandle_Close"; | 9 static int close(int handle) native "MojoHandle_Close"; |
10 static List wait( | 10 static List wait( |
11 int handle, int signals, int deadline) native "MojoHandle_Wait"; | 11 int handle, int signals, int deadline) native "MojoHandle_Wait"; |
12 static List waitMany(List<int> handles, List<int> signals, | 12 static List waitMany(List<int> handles, List<int> signals, |
13 int deadline) native "MojoHandle_WaitMany"; | 13 int deadline) native "MojoHandle_WaitMany"; |
14 } | 14 } |
15 | 15 |
16 class _HandleCreationRecord { | |
17 final MojoHandle handle; | |
18 final StackTrace stack; | |
19 _HandleCreationRecord(this.handle, this.stack); | |
20 } | |
21 | |
16 class MojoHandle { | 22 class MojoHandle { |
17 static const int INVALID = 0; | 23 static const int INVALID = 0; |
18 static const int DEADLINE_INDEFINITE = -1; | 24 static const int DEADLINE_INDEFINITE = -1; |
19 | 25 |
20 int h; | 26 int _h; |
27 int get h => _h; | |
21 | 28 |
22 MojoHandle(this.h); | 29 MojoHandle(this._h) { |
30 assert(_addUnclosedHandle(this)); | |
31 } | |
32 | |
33 MojoHandle._internal(this._h); | |
34 | |
35 MojoHandle.invalid() : this._internal(INVALID); | |
23 | 36 |
24 MojoResult close() { | 37 MojoResult close() { |
25 int result = _MojoHandleNatives.close(h); | 38 assert(_removeUnclosedHandle(this)); |
26 h = INVALID; | 39 int result = _MojoHandleNatives.close(_h); |
40 _h = INVALID; | |
27 return new MojoResult(result); | 41 return new MojoResult(result); |
28 } | 42 } |
29 | 43 |
44 MojoHandle pass() { | |
45 assert(_removeUnclosedHandle(this)); | |
46 return this; | |
47 } | |
48 | |
30 MojoWaitResult wait(int signals, int deadline) { | 49 MojoWaitResult wait(int signals, int deadline) { |
31 List result = _MojoHandleNatives.wait(h, signals, deadline); | 50 List result = _MojoHandleNatives.wait(h, signals, deadline); |
32 return new MojoWaitResult(new MojoResult(result[0]), result[1]); | 51 return new MojoWaitResult(new MojoResult(result[0]), result[1]); |
33 } | 52 } |
34 | 53 |
35 bool _ready(MojoHandleSignals signal) { | 54 bool _ready(MojoHandleSignals signal) { |
36 MojoWaitResult mwr = wait(signal.value, 0); | 55 MojoWaitResult mwr = wait(signal.value, 0); |
37 switch (mwr.result) { | 56 switch (mwr.result) { |
38 case MojoResult.OK: | 57 case MojoResult.OK: |
39 return true; | 58 return true; |
40 case MojoResult.DEADLINE_EXCEEDED: | 59 case MojoResult.DEADLINE_EXCEEDED: |
41 case MojoResult.CANCELLED: | 60 case MojoResult.CANCELLED: |
42 case MojoResult.INVALID_ARGUMENT: | 61 case MojoResult.INVALID_ARGUMENT: |
43 case MojoResult.FAILED_PRECONDITION: | 62 case MojoResult.FAILED_PRECONDITION: |
44 return false; | 63 return false; |
45 default: | 64 default: |
46 // Should be unreachable. | 65 // Should be unreachable. |
47 throw "Unexpected result $res for wait on $h"; | 66 throw "Unexpected result $mwr for wait on $h"; |
48 } | 67 } |
49 } | 68 } |
50 | 69 |
70 void _set(int value) { | |
71 _h = value; | |
72 } | |
73 | |
51 bool get readyRead => _ready(MojoHandleSignals.PEER_CLOSED_READABLE); | 74 bool get readyRead => _ready(MojoHandleSignals.PEER_CLOSED_READABLE); |
52 bool get readyWrite => _ready(MojoHandleSignals.WRITABLE); | 75 bool get readyWrite => _ready(MojoHandleSignals.WRITABLE); |
76 bool get isValid => (_h != INVALID); | |
77 | |
78 String toString() { | |
79 if (!isValid) { | |
80 return "MojoHandle(INVALID)"; | |
81 } | |
82 var mwr = wait(MojoHandleSignals.kAll, 0); | |
83 return "MojoHandle(h: $h, status: $mwr)"; | |
84 } | |
85 | |
86 bool operator ==(MojoHandle other) { | |
87 return _h == other._h; | |
88 } | |
53 | 89 |
54 static MojoWaitManyResult waitMany( | 90 static MojoWaitManyResult waitMany( |
55 List<int> handles, List<int> signals, int deadline) { | 91 List<int> handles, List<int> signals, int deadline) { |
56 List result = _MojoHandleNatives.waitMany(handles, signals, deadline); | 92 List result = _MojoHandleNatives.waitMany(handles, signals, deadline); |
57 return new MojoWaitManyResult( | 93 return new MojoWaitManyResult( |
58 new MojoResult(result[0]), result[1], result[2]); | 94 new MojoResult(result[0]), result[1], result[2]); |
59 } | 95 } |
60 | 96 |
61 static MojoResult register(MojoEventStream eventStream) { | 97 static MojoResult register(MojoEventStream eventStream) { |
62 return new MojoResult(_MojoHandleNatives.register(eventStream)); | 98 return new MojoResult(_MojoHandleNatives.register(eventStream)); |
63 } | 99 } |
64 | 100 |
65 bool get isValid => (h != INVALID); | 101 static HashMap<int, _HandleCreationRecord> _unclosedHandles = new HashMap(); |
66 | 102 |
67 String toString() { | 103 // _addUnclosedHandle(), _removeUnclosedHandle(), and dumpLeakedHandles() |
68 if (!isValid) { | 104 // should only be used inside of assert() statements. |
69 return "MojoHandle(INVALID)"; | 105 static bool _addUnclosedHandle(MojoHandle handle) { |
106 var stack; | |
107 try { | |
108 assert(false); | |
sky
2015/03/11 17:17:57
Ick.
zra
2015/03/11 18:58:20
In case someone accidentally uses one of these cal
| |
109 } catch (_, s) { | |
110 stack = s; | |
70 } | 111 } |
71 var mwr = wait(MojoHandleSignals.kAll, 0); | 112 |
72 return "MojoHandle(h: $h, status: $mwr)"; | 113 var handleCreate = new _HandleCreationRecord(handle, stack); |
114 _unclosedHandles[handle.h] = handleCreate; | |
115 return true; | |
sky
2015/03/11 17:17:57
Is there a reason you have a return value here sin
zra
2015/03/11 18:58:20
Making these calls only inside of assert() stateme
sky
2015/03/11 19:17:24
Ah, tricky. Got it.
| |
73 } | 116 } |
74 | 117 |
75 bool operator ==(MojoHandle other) { | 118 static bool _removeUnclosedHandle(MojoHandle handle) { |
76 return h == other.h; | 119 _unclosedHandles.remove(handle._h); |
120 return true; | |
sky
2015/03/11 17:17:57
Same comment here about always true return value.
zra
2015/03/11 18:58:20
Same reason.
| |
121 } | |
122 | |
123 static bool reportLeakedHandles() { | |
124 var noleaks = true; | |
125 for (var handle in MojoHandle._unclosedHandles.keys) { | |
126 var handleCreation = MojoHandle._unclosedHandles[handle]; | |
127 if (handleCreation != null) { | |
128 print("HANDLE LEAK: handle: $handle, created at:"); | |
129 print("${handleCreation.stack}"); | |
130 noleaks = false; | |
131 } | |
132 } | |
133 return noleaks; | |
77 } | 134 } |
78 } | 135 } |
OLD | NEW |