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 $mwr 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); |
| 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; |
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; |
| 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 |