blob: e7ac3eb811f713bfde081072176ea855fa3b72fd [file] [log] [blame] [edit]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of core;
class _HandleCreationRecord {
final MojoHandle handle;
final StackTrace stack;
_HandleCreationRecord(this.handle, this.stack);
}
class MojoHandle {
static const int INVALID = 0;
static const int DEADLINE_INDEFINITE = -1;
int _h;
int get h => _h;
MojoHandle(this._h) {
assert(_addUnclosedHandle(this));
}
MojoHandle._internal(this._h);
MojoHandle.invalid() : this._internal(INVALID);
MojoResult close() {
assert(_removeUnclosedHandle(this));
int result = MojoHandleNatives.close(_h);
_h = INVALID;
return new MojoResult(result);
}
MojoHandle pass() {
assert(_removeUnclosedHandle(this));
return this;
}
MojoWaitResult wait(int signals, int deadline) {
List result = MojoHandleNatives.wait(h, signals, deadline);
var state = result[1] != null
? new MojoHandleSignalsState(result[1][0], result[1][1])
: null;
return new MojoWaitResult(new MojoResult(result[0]), state);
}
bool _ready(MojoHandleSignals signal) {
MojoWaitResult mwr = wait(signal.value, 0);
switch (mwr.result) {
case MojoResult.OK:
return true;
case MojoResult.DEADLINE_EXCEEDED:
case MojoResult.CANCELLED:
case MojoResult.INVALID_ARGUMENT:
case MojoResult.FAILED_PRECONDITION:
return false;
default:
// Should be unreachable.
throw "Unexpected result $mwr for wait on $h";
}
}
void _set(int value) {
_h = value;
}
bool get readyRead => _ready(MojoHandleSignals.PEER_CLOSED_READABLE);
bool get readyWrite => _ready(MojoHandleSignals.WRITABLE);
bool get isValid => (_h != INVALID);
String toString() {
if (!isValid) {
return "MojoHandle(INVALID)";
}
var mwr = wait(MojoHandleSignals.kAll, 0);
return "MojoHandle(h: $h, status: $mwr)";
}
bool operator ==(MojoHandle other) {
return _h == other._h;
}
static MojoWaitManyResult waitMany(
List<int> handles, List<int> signals, int deadline) {
List result = MojoHandleNatives.waitMany(handles, signals, deadline);
List states = result[2] != null
? result[2].map((l) => new MojoHandleSignalsState(l[0], l[1])).toList()
: null;
return new MojoWaitManyResult(new MojoResult(result[0]), result[1], states);
}
static MojoResult register(MojoEventStream eventStream) {
return new MojoResult(
MojoHandleNatives.register(eventStream, eventStream._handle.h));
}
static HashMap<int, _HandleCreationRecord> _unclosedHandles = new HashMap();
// _addUnclosedHandle(), _removeUnclosedHandle(), and dumpLeakedHandles()
// should only be used inside of assert() statements.
static bool _addUnclosedHandle(MojoHandle handle) {
var stack;
try {
assert(false);
} catch (_, s) {
stack = s;
}
var handleCreate = new _HandleCreationRecord(handle, stack);
_unclosedHandles[handle.h] = handleCreate;
return true;
}
static bool _removeUnclosedHandle(MojoHandle handle) {
_unclosedHandles.remove(handle._h);
return true;
}
static bool reportLeakedHandles() {
var noleaks = true;
for (var handle in MojoHandle._unclosedHandles.keys) {
var handleCreation = MojoHandle._unclosedHandles[handle];
if (handleCreation != null) {
print("HANDLE LEAK: handle: $handle, created at:");
print("${handleCreation.stack}");
noleaks = false;
}
}
return noleaks;
}
}