Files
sdk/runtime/vm/message_queue.cc
T
turnidge@google.com 8920623dc5 OOB messages and general message refactor.
(1)
No longer give embedders direct access to inter-isolate messages.
Instead, keep these messages in an internal queue and rely on the
embedder only to provide notifications.  This simplifies the api in
numerous ways:

 - post message callback drops parameters and becomes message notify callback.
 - close port callback goes away
 - Dart_Message type goes away
 - Dart_HandleMessage gets a simpler signature

Updated the custom_isolate_test to show what use of the new apis looks like.

(2)
Begin to add support for out-of-band (OOB) messages.  These messages
supercede regular messages in the queue.  We will attempt to deliver
these messages even while code is running, by using the isolate
interrupt mechanism.  These messages are not user-visible.  They will
be used by the runtime internally to implement things like reflection.

Renamed PortMessage to Message.

Refactored message sending apis in PortMap and Isolate.

Modified MessageQueue to be aware of multiple priorities.

Modify Dart_HandleMessage to process multiple OOB messages
Review URL: https://chromiumcodereview.appspot.com//9182001

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3562 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-24 19:31:01 +00:00

135 lines
3.2 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_queue.h"
namespace dart {
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) {
// TODO(turnidge): Add a scoped locker for monitors which is not a
// stack resource. This would probably be useful in the platform
// headers.
monitor_.Enter();
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;
}
monitor_.Exit();
}
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.
ml.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