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