Flutter Engine
The Flutter Engine
dart_vm_lifecycle.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/runtime/dart_vm_lifecycle.h"
6
7#include <mutex>
8#include <utility>
9
10namespace flutter {
11
12// We need to explicitly put the constructor and destructor of the DartVM in the
13// critical section. All accesses (not just const members) to the global VM
14// object weak pointer are behind this mutex.
15static std::mutex gVMMutex;
16static std::weak_ptr<DartVM> gVM;
17static std::shared_ptr<DartVM>* gVMLeak;
18
19// We are going to be modifying more than just the control blocks of the
20// following weak pointers (in the |Create| case where an old VM could not be
21// reused). Ideally, we would use |std::atomic<std::weak_ptr<T>>| specialization
22// but that is only available since C++20. We don't expect contention on these
23// locks so we just use one mutex for all.
24static std::mutex gVMDependentsMutex;
25static std::weak_ptr<const DartVMData> gVMData;
26static std::weak_ptr<ServiceProtocol> gVMServiceProtocol;
27static std::weak_ptr<IsolateNameServer> gVMIsolateNameServer;
28
29DartVMRef::DartVMRef(std::shared_ptr<DartVM> vm) : vm_(std::move(vm)) {}
30
31DartVMRef::DartVMRef(DartVMRef&& other) = default;
32
33DartVMRef::~DartVMRef() {
34 if (!vm_) {
35 // If there is no valid VM (possible via a move), there is no way that the
36 // decrement on the shared pointer can cause a collection. Avoid acquiring
37 // the lifecycle lock in this case. This is just working around a
38 // pessimization and not required for correctness.
39 return;
40 }
41 std::scoped_lock lifecycle_lock(gVMMutex);
42 vm_.reset();
43}
44
47 fml::RefPtr<const DartSnapshot> isolate_snapshot) {
48 std::scoped_lock lifecycle_lock(gVMMutex);
49
50 if (!settings.leak_vm) {
52 << "Launch settings indicated that the VM should shut down in the "
53 "process when done but a previous launch asked the VM to leak in "
54 "the same process. For proper VM shutdown, all VM launches must "
55 "indicate that they should shut down when done.";
56 }
57
58 // If there is already a running VM in the process, grab a strong reference to
59 // it.
60 if (auto vm = gVM.lock()) {
61 FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
62 "already running. Ignoring arguments for current VM "
63 "create call and reusing the old VM.";
64 // There was already a running VM in the process,
65 return DartVMRef{std::move(vm)};
66 }
67
68 std::scoped_lock dependents_lock(gVMDependentsMutex);
69
70 gVMData.reset();
71 gVMServiceProtocol.reset();
73 gVM.reset();
74
75 // If there is no VM in the process. Initialize one, hold the weak reference
76 // and pass a strong reference to the caller.
77 auto isolate_name_server = std::make_shared<IsolateNameServer>();
78 auto vm = DartVM::Create(settings, //
79 std::move(vm_snapshot), //
80 std::move(isolate_snapshot), //
81 isolate_name_server //
82 );
83
84 if (!vm) {
85 FML_LOG(ERROR) << "Could not create Dart VM instance.";
86 return DartVMRef{nullptr};
87 }
88
89 gVMData = vm->GetVMData();
90 gVMServiceProtocol = vm->GetServiceProtocol();
91 gVMIsolateNameServer = isolate_name_server;
92 gVM = vm;
93
94 if (settings.leak_vm) {
95 gVMLeak = new std::shared_ptr<DartVM>(vm);
96 }
97
98 return DartVMRef{std::move(vm)};
99}
100
101bool DartVMRef::IsInstanceRunning() {
102 std::scoped_lock lock(gVMMutex);
103 return !gVM.expired();
104}
105
106std::shared_ptr<const DartVMData> DartVMRef::GetVMData() {
107 std::scoped_lock lock(gVMDependentsMutex);
108 return gVMData.lock();
109}
110
111std::shared_ptr<ServiceProtocol> DartVMRef::GetServiceProtocol() {
112 std::scoped_lock lock(gVMDependentsMutex);
113 return gVMServiceProtocol.lock();
114}
115
116std::shared_ptr<IsolateNameServer> DartVMRef::GetIsolateNameServer() {
117 std::scoped_lock lock(gVMDependentsMutex);
118 return gVMIsolateNameServer.lock();
119}
120
121DartVM* DartVMRef::GetRunningVM() {
122 std::scoped_lock lock(gVMMutex);
123 auto vm = gVM.lock().get();
124 FML_CHECK(vm) << "Caller assumed VM would be running when it wasn't";
125 return vm;
126}
127
128} // namespace flutter
static sk_sp< Effect > Create()
Definition: RefCntTest.cpp:117
DartVMRef(const DartVMRef &)=default
Describes a running instance of the Dart VM. There may only be one running instance of the Dart VM in...
Definition: dart_vm.h:61
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
static std::weak_ptr< IsolateNameServer > gVMIsolateNameServer
static std::weak_ptr< ServiceProtocol > gVMServiceProtocol
static std::mutex gVMMutex
static std::mutex gVMDependentsMutex
static std::weak_ptr< DartVM > gVM
static std::weak_ptr< const DartVMData > gVMData
static std::shared_ptr< DartVM > * gVMLeak
Definition: ref_ptr.h:256
#define ERROR(message)
Definition: elf_loader.cc:260