mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:22:12 +00:00
1f5364cd3b
Dart_NewNativePort creates a port associated with a C handler function. When messages come in on this port, they are forwarded to the C function for processing. To support this, refactored PortMap so that it operates on a new MessageHandler type instead of directly on Isolates. For now, native ports have a dedicated single thread. Eventually we will back native ports (and possibly Isolates as well) by a shared thread pool. Review URL: https://chromiumcodereview.appspot.com//9169063 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3804 260f80e4-7a28-3924-810f-c04153c831b5
194 lines
4.4 KiB
C++
194 lines
4.4 KiB
C++
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/message.h"
|
|
|
|
namespace dart {
|
|
|
|
DECLARE_FLAG(bool, trace_isolates);
|
|
|
|
|
|
MessageHandler::MessageHandler()
|
|
: live_ports_(0),
|
|
queue_(new MessageQueue()) {
|
|
ASSERT(queue_ != NULL);
|
|
}
|
|
|
|
|
|
MessageHandler::~MessageHandler() {
|
|
delete queue_;
|
|
}
|
|
|
|
|
|
const char* MessageHandler::name() const {
|
|
return "<unnamed>";
|
|
}
|
|
|
|
|
|
#if defined(DEBUG)
|
|
void MessageHandler::CheckAccess() {
|
|
// By default there is no checking.
|
|
}
|
|
#endif
|
|
|
|
|
|
void MessageHandler::MessageNotify(Message::Priority priority) {
|
|
// By default, there is no custom message notification.
|
|
}
|
|
|
|
|
|
void MessageHandler::PostMessage(Message* message) {
|
|
if (FLAG_trace_isolates) {
|
|
const char* source_name = "<native code>";
|
|
Isolate* source_isolate = Isolate::Current();
|
|
if (source_isolate) {
|
|
source_name = source_isolate->name();
|
|
}
|
|
OS::Print("[>] Posting message:\n"
|
|
"\tsource: %s\n"
|
|
"\treply_port: %lld\n"
|
|
"\tdest: %s\n"
|
|
"\tdest_port: %lld\n",
|
|
source_name, message->reply_port(), name(), message->dest_port());
|
|
}
|
|
|
|
Message::Priority priority = message->priority();
|
|
queue()->Enqueue(message);
|
|
message = NULL; // Do not access message. May have been deleted.
|
|
|
|
// Invoke any custom message notification.
|
|
MessageNotify(priority);
|
|
}
|
|
|
|
|
|
void MessageHandler::ClosePort(Dart_Port port) {
|
|
queue()->Flush(port);
|
|
}
|
|
|
|
|
|
void MessageHandler::CloseAllPorts() {
|
|
queue()->FlushAll();
|
|
}
|
|
|
|
|
|
MessageQueue::MessageQueue() {
|
|
for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) {
|
|
head_[p] = NULL;
|
|
tail_[p] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
MessageQueue::~MessageQueue() {
|
|
// Ensure that all pending messages have been released.
|
|
#if defined(DEBUG)
|
|
for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) {
|
|
ASSERT(head_[p] == NULL);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void MessageQueue::Enqueue(Message* msg) {
|
|
MonitorLocker ml(&monitor_);
|
|
Message::Priority p = msg->priority();
|
|
// Make sure messages are not reused.
|
|
ASSERT(msg->next_ == NULL);
|
|
if (head_[p] == NULL) {
|
|
// Only element in the queue.
|
|
head_[p] = msg;
|
|
tail_[p] = msg;
|
|
|
|
// We only need to notify if the queue was empty.
|
|
monitor_.Notify();
|
|
} else {
|
|
ASSERT(tail_[p] != NULL);
|
|
// Append at the tail.
|
|
tail_[p]->next_ = msg;
|
|
tail_[p] = msg;
|
|
}
|
|
}
|
|
|
|
Message* MessageQueue::DequeueNoWait() {
|
|
MonitorLocker ml(&monitor_);
|
|
return DequeueNoWaitHoldsLock();
|
|
}
|
|
|
|
Message* MessageQueue::DequeueNoWaitHoldsLock() {
|
|
// Look for the highest priority available message.
|
|
for (int p = Message::kNumPriorities-1; p >= Message::kFirstPriority; p--) {
|
|
Message* result = head_[p];
|
|
if (result != NULL) {
|
|
head_[p] = result->next_;
|
|
// The following update to tail_ is not strictly needed.
|
|
if (head_[p] == NULL) {
|
|
tail_[p] = NULL;
|
|
}
|
|
#if defined(DEBUG)
|
|
result->next_ = result; // Make sure to trigger ASSERT in Enqueue.
|
|
#endif // DEBUG
|
|
return result;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
Message* MessageQueue::Dequeue(int64_t millis) {
|
|
ASSERT(millis >= 0);
|
|
MonitorLocker ml(&monitor_);
|
|
Message* result = DequeueNoWaitHoldsLock();
|
|
if (result == NULL) {
|
|
// No message available at any priority.
|
|
monitor_.Wait(millis);
|
|
result = DequeueNoWaitHoldsLock();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
void MessageQueue::Flush(Dart_Port port) {
|
|
MonitorLocker ml(&monitor_);
|
|
for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) {
|
|
Message* cur = head_[p];
|
|
Message* prev = NULL;
|
|
while (cur != NULL) {
|
|
Message* next = cur->next_;
|
|
// If the message matches, then remove it from the queue and delete it.
|
|
if (cur->dest_port() == port) {
|
|
if (prev != NULL) {
|
|
prev->next_ = next;
|
|
} else {
|
|
head_[p] = next;
|
|
}
|
|
delete cur;
|
|
} else {
|
|
// Move prev forward.
|
|
prev = cur;
|
|
}
|
|
// Advance to the next message in the queue.
|
|
cur = next;
|
|
}
|
|
tail_[p] = prev;
|
|
}
|
|
}
|
|
|
|
|
|
void MessageQueue::FlushAll() {
|
|
MonitorLocker ml(&monitor_);
|
|
for (int p = Message::kFirstPriority; p < Message::kNumPriorities; p++) {
|
|
Message* cur = head_[p];
|
|
head_[p] = NULL;
|
|
tail_[p] = NULL;
|
|
while (cur != NULL) {
|
|
Message* next = cur->next_;
|
|
delete cur;
|
|
cur = next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace dart
|