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