| // 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() {} | |
| 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 |