Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Unified Diff: runtime/vm/port.cc

Issue 8297004: Allow embedders to provide custom message delivery for an isolate. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/port.h ('k') | runtime/vm/port_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/port.cc
===================================================================
--- runtime/vm/port.cc (revision 513)
+++ runtime/vm/port.cc (working copy)
@@ -4,82 +4,13 @@
#include "vm/port.h"
+#include "vm/isolate.h"
+#include "vm/thread.h"
+#include "vm/utils.h"
+
namespace dart {
-MessageQueue::~MessageQueue() {
- // Ensure that all pending messages have been released.
- ASSERT(head_ == NULL);
-}
-
-void MessageQueue::Enqueue(PortMessage* msg) {
- // Make sure messages are not reused.
- ASSERT(msg->next_ == NULL);
- if (head_ == NULL) {
- // Only element in the queue.
- head_ = msg;
- tail_ = msg;
- } else {
- ASSERT(tail_ != NULL);
- // Append at the tail.
- tail_->next_ = msg;
- tail_ = msg;
- }
-}
-
-
-PortMessage* MessageQueue::Dequeue() {
- PortMessage* result = head_;
- if (result != NULL) {
- head_ = result->next_;
- // The following update to tail_ is not strictly needed.
- if (head_ == NULL) {
- tail_ = NULL;
- }
-#if DEBUG
- result->next_ = result; // Make sure to trigger ASSERT in Enqueue.
-#endif // DEBUG
- }
- return result;
-}
-
-
-void MessageQueue::Flush(intptr_t port_id) {
- PortMessage* cur = head_;
- PortMessage* prev = NULL;
- while (cur != NULL) {
- PortMessage* next = cur->next_;
- // If the message matches, then remove it from the queue and delete it.
- if (cur->dest_id() == port_id) {
- if (prev != NULL) {
- prev->next_ = next;
- } else {
- head_ = next;
- }
- delete cur;
- } else {
- // Move prev forward.
- prev = cur;
- }
- // Advance to the next message in the queue.
- cur = next;
- }
- tail_ = prev;
-}
-
-
-void MessageQueue::FlushAll() {
- PortMessage* cur = head_;
- head_ = NULL;
- tail_ = NULL;
- while (cur != NULL) {
- PortMessage* next = cur->next_;
- delete next;
- cur = next;
- }
-}
-
-
Mutex* PortMap::mutex_ = NULL;
PortMap::Entry* PortMap::map_ = NULL;
@@ -88,15 +19,15 @@
intptr_t PortMap::used_ = 0;
intptr_t PortMap::deleted_ = 0;
-intptr_t PortMap::next_id_ = 7111;
+Dart_Port PortMap::next_port_ = 7111;
-intptr_t PortMap::FindId(intptr_t id) {
- intptr_t index = id % capacity_;
+intptr_t PortMap::FindPort(Dart_Port port) {
+ intptr_t index = port % capacity_;
intptr_t start_index = index;
Entry entry = map_[index];
while (entry.isolate != NULL) {
- if (entry.id == id) {
+ if (entry.port == port) {
return index;
}
index = (index + 1) % capacity_;
@@ -115,9 +46,9 @@
for (intptr_t i = 0; i < capacity_; i++) {
Entry entry = map_[i];
// Skip free and deleted entries.
- if (entry.id != 0) {
- intptr_t new_index = entry.id % new_capacity;
- while (new_ports[new_index].id != 0) {
+ if (entry.port != 0) {
+ intptr_t new_index = entry.port % new_capacity;
+ while (new_ports[new_index].port != 0) {
new_index = (new_index + 1) % new_capacity;
}
new_ports[new_index] = entry;
@@ -130,14 +61,14 @@
}
-intptr_t PortMap::AllocateId() {
- intptr_t result = next_id_;
+Dart_Port PortMap::AllocatePort() {
+ Dart_Port result = next_port_;
do {
// TODO(iposva): Use an approved hashing function to have less predictable
// port ids, or make them not accessible from Dart code or both.
- next_id_++;
- } while (FindId(next_id_) >= 0);
+ next_port_++;
+ } while (FindPort(next_port_) >= 0);
ASSERT(result != 0);
return result;
@@ -157,22 +88,22 @@
}
-intptr_t PortMap::CreatePort() {
+Dart_Port PortMap::CreatePort() {
Isolate* isolate = Isolate::Current();
MutexLocker ml(mutex_);
Entry entry;
- entry.id = AllocateId();
+ entry.port = AllocatePort();
entry.isolate = isolate;
// Search for the first unused slot. Make use of the knowledge that here is
// currently no port with this id in the port map.
- ASSERT(FindId(entry.id) < 0);
- intptr_t index = entry.id % capacity_;
+ ASSERT(FindPort(entry.port) < 0);
+ intptr_t index = entry.port % capacity_;
Entry cur = map_[index];
// Stop the search at the first found unused (free or deleted) slot.
- while (cur.id != 0) {
+ while (cur.port != 0) {
index = (index + 1) % capacity_;
cur = map_[index];
}
@@ -180,7 +111,7 @@
// Insert the newly created port at the index.
ASSERT(index >= 0);
ASSERT(index < capacity_);
- ASSERT(map_[index].id == 0);
+ ASSERT(map_[index].port == 0);
ASSERT((map_[index].isolate == NULL) ||
(map_[index].isolate == deleted_entry_));
if (map_[index].isolate == deleted_entry_) {
@@ -194,25 +125,25 @@
used_++;
MaintainInvariants();
- return entry.id;
+ return entry.port;
}
-void PortMap::ClosePort(intptr_t id) {
+void PortMap::ClosePort(Dart_Port port) {
Isolate* isolate = Isolate::Current();
{
MutexLocker ml(mutex_);
- intptr_t index = FindId(id);
+ intptr_t index = FindPort(port);
if (index < 0) {
return;
}
ASSERT(index < capacity_);
- ASSERT(map_[index].id != 0);
+ ASSERT(map_[index].port != 0);
ASSERT(map_[index].isolate == isolate);
// Before releasing the lock mark the slot in the map as deleted. This makes
// it possible to release the port map lock before flushing all of its
// pending messages below.
- map_[index].id = 0;
+ map_[index].port = 0;
map_[index].isolate = deleted_entry_;
isolate->decrement_active_ports();
@@ -220,11 +151,12 @@
deleted_++;
MaintainInvariants();
}
- {
- // Remove the pending messages for this port.
- MonitorLocker ml(isolate->monitor());
- isolate->message_queue()->Flush(id);
- }
+
+ // Notify the embedder that this port is closed.
+ Dart_ClosePortCallback callback = isolate->close_port_callback();
+ ASSERT(callback);
+ ASSERT(port != kCloseAllPorts);
+ (*callback)(isolate, port);
}
@@ -235,7 +167,7 @@
for (intptr_t i = 0; i < capacity_; i++) {
if (map_[i].isolate == isolate) {
// Mark the slot as deleted.
- map_[i].id = 0;
+ map_[i].port = 0;
map_[i].isolate = deleted_entry_;
isolate->decrement_active_ports();
@@ -245,54 +177,43 @@
}
MaintainInvariants();
}
- isolate->message_queue()->FlushAll();
+
+ // Notify the embedder that all ports are closed.
+ Dart_ClosePortCallback callback = isolate->close_port_callback();
+ ASSERT(callback);
+ (*callback)(isolate, kCloseAllPorts);
}
-bool PortMap::IsActivePort(intptr_t id) {
+bool PortMap::IsActivePort(Dart_Port port) {
MutexLocker ml(mutex_);
- return (FindId(id) >= 0);
+ return (FindPort(port) >= 0);
}
-bool PortMap::PostMessage(PortMessage* msg) {
- intptr_t id = msg->dest_id();
+bool PortMap::PostMessage(Dart_Port dest_port,
+ Dart_Port reply_port,
+ Dart_Message message) {
mutex_->Lock();
- intptr_t index = FindId(id);
+ intptr_t index = FindPort(dest_port);
if (index < 0) {
+ free(message);
mutex_->Unlock();
return false;
}
ASSERT(index >= 0);
ASSERT(index < capacity_);
Isolate* isolate = map_[index].isolate;
- ASSERT(map_[index].id != 0);
+ ASSERT(map_[index].port != 0);
ASSERT((isolate != NULL) && (isolate != deleted_entry_));
- Monitor* monitor = isolate->monitor();
- monitor->Enter();
- isolate->message_queue()->Enqueue(msg);
- monitor->Notify();
- monitor->Exit();
- mutex_->Unlock();
- return true;
-}
+ // Delegate message delivery to the embedder.
+ Dart_PostMessageCallback callback = isolate->post_message_callback();
+ ASSERT(callback);
+ bool result = (*callback)(isolate, dest_port, reply_port, message);
-PortMessage* PortMap::ReceiveMessage(int64_t millis) {
- // Since only the isolate owning the port can close the port and remove it
- // from the port map and flush its messages, we can safely assume that the
- // all messages in the message queue are for active ports.
- Isolate* isolate = Isolate::Current();
- {
- MonitorLocker ml(isolate->monitor());
- PortMessage* result = isolate->message_queue()->Dequeue();
- if (result == NULL) {
- ml.Wait(millis);
- result = isolate->message_queue()->Dequeue();
- // We will return a NULL message for spurious wakeups or timeouts.
- }
- return result;
- }
+ mutex_->Unlock();
+ return result;
}
« no previous file with comments | « runtime/vm/port.h ('k') | runtime/vm/port_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698