blob: dcc8c33076a7d6911920dbb4af5390ad1d91cf1f [file] [log] [blame] [edit]
// Copyright (c) 2012, 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/native_message_handler.h"
#include <memory>
#include <utility>
#include "vm/dart_api_message.h"
#include "vm/isolate.h"
#include "vm/message.h"
#include "vm/message_snapshot.h"
#include "vm/snapshot.h"
namespace dart {
Monitor* NativeMessageHandler::monitor_ = nullptr;
intptr_t NativeMessageHandler::pending_deletions_ = 0;
NativeMessageHandler::NativeMessageHandler(const char* name,
Dart_NativeMessageHandler func,
intptr_t max_concurrency)
: name_(Utils::StrDup(name)), func_(func), pool_(max_concurrency) {}
NativeMessageHandler::~NativeMessageHandler() {}
#if defined(DEBUG)
void NativeMessageHandler::CheckAccess() const {
ASSERT(Isolate::Current() == nullptr);
}
#endif
namespace {
class HandleMessage : public ThreadPool::Task {
public:
HandleMessage(Dart_NativeMessageHandler handler,
std::unique_ptr<Message> message)
: handler_(handler), message_(std::move(message)) {
ASSERT(handler != nullptr);
}
virtual void Run() {
ApiNativeScope scope;
Dart_CObject* object = ReadApiMessage(scope.zone(), message_.get());
handler_(message_->dest_port(), object);
}
private:
Dart_NativeMessageHandler handler_;
std::unique_ptr<Message> message_;
DISALLOW_COPY_AND_ASSIGN(HandleMessage);
};
} // namespace
void NativeMessageHandler::PostMessage(std::unique_ptr<Message> message,
bool before_events /* = false */) {
if (message->IsOOB()) {
UNREACHABLE();
}
pool_.Run<HandleMessage>(func_, std::move(message));
}
void NativeMessageHandler::RequestDeletion(NativeMessageHandler* handler) {
{
MonitorLocker ml(monitor_);
pending_deletions_++;
}
ThreadPool::RequestShutdown(&handler->pool_, [handler]() {
delete handler;
// Once the handler and its pool is gone make sure to wake up
// |NativeMessageHandler::Cleanup| which might be waiting.
{
MonitorLocker ml(monitor_);
pending_deletions_--;
if (pending_deletions_ == 0) {
ml.Notify();
}
}
});
}
void NativeMessageHandler::Shutdown() {
pool_.Shutdown();
}
void NativeMessageHandler::Init() {
monitor_ = new Monitor();
}
void NativeMessageHandler::Cleanup() {
{
MonitorLocker ml(monitor_);
// By the time we get here we don't really expect new deletions to be
// requested. We proceed with VM shutdown once we have no pending deletions.
// In other words words don't try to guard against a race between
// |Dart_CloseNativePort| and |Dart_Cleanup| - that's considered an API
// misuse.
while (pending_deletions_ > 0) {
ml.Wait();
}
}
delete monitor_;
monitor_ = nullptr;
}
} // namespace dart