Coverage Report

Created: 2025-07-23 06:30

/src/WasmEdge/include/runtime/storemgr.h
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
//===-- wasmedge/runtime/storemgr.h - Store Manager definition ------------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the definition of Store Manager.
12
///
13
//===----------------------------------------------------------------------===//
14
#pragma once
15
16
#include "runtime/instance/component.h"
17
#include "runtime/instance/module.h"
18
19
#include <mutex>
20
#include <shared_mutex>
21
#include <vector>
22
23
namespace WasmEdge {
24
25
namespace Executor {
26
class Executor;
27
}
28
29
namespace Runtime {
30
31
class StoreManager {
32
public:
33
0
  StoreManager() = default;
34
0
  ~StoreManager() {
35
    // When destroying this store manager, unlink all the registered module
36
    // instances.
37
0
    reset();
38
0
  }
39
40
  /// Get the length of the list of registered modules.
41
0
  uint32_t getModuleListSize() const noexcept {
42
0
    std::shared_lock Lock(Mutex);
43
0
    return static_cast<uint32_t>(NamedMod.size());
44
0
  }
45
46
  /// Get list of registered modules.
47
0
  template <typename CallbackT> auto getModuleList(CallbackT &&CallBack) const {
48
0
    std::shared_lock Lock(Mutex);
49
0
    return std::forward<CallbackT>(CallBack)(NamedMod);
50
0
  }
Unexecuted instantiation: wasmedge.cpp:auto WasmEdge::Runtime::StoreManager::getModuleList<WasmEdge_StoreListModule::$_0>(WasmEdge_StoreListModule::$_0&&) const
Unexecuted instantiation: wasmedge.cpp:auto WasmEdge::Runtime::StoreManager::getModuleList<WasmEdge_VMListRegisteredModule::$_0>(WasmEdge_VMListRegisteredModule::$_0&&) const
51
52
  /// Find module by name.
53
0
  const Instance::ModuleInstance *findModule(std::string_view Name) const {
54
0
    std::shared_lock Lock(Mutex);
55
0
    if (auto Iter = SoftNamedMod.find(Name);
56
0
        likely(Iter != SoftNamedMod.cend())) {
57
0
      return Iter->second;
58
0
    }
59
0
    if (auto Iter = NamedMod.find(Name); likely(Iter != NamedMod.cend())) {
60
0
      return Iter->second;
61
0
    }
62
0
    return nullptr;
63
0
  }
64
  const Instance::ComponentInstance *
65
0
  findComponent(std::string_view Name) const {
66
0
    std::shared_lock Lock(Mutex);
67
0
    if (auto Iter = NamedComp.find(Name); likely(Iter != NamedComp.cend())) {
68
0
      return Iter->second;
69
0
    }
70
0
    return nullptr;
71
0
  }
72
73
  /// Reset this store manager and unlink all the registered module instances.
74
0
  void reset() noexcept {
75
0
    std::shared_lock Lock(Mutex);
76
0
    for (auto &&Pair : NamedMod) {
77
0
      (const_cast<Instance::ModuleInstance *>(Pair.second))->unlinkStore(this);
78
0
    }
79
0
    NamedMod.clear();
80
0
  }
81
82
  /// Register named module into this store.
83
0
  Expect<void> registerModule(const Instance::ModuleInstance *ModInst) {
84
0
    std::unique_lock Lock(Mutex);
85
0
    auto Iter = NamedMod.find(ModInst->getModuleName());
86
0
    if (likely(Iter != NamedMod.cend())) {
87
0
      return Unexpect(ErrCode::Value::ModuleNameConflict);
88
0
    }
89
0
    NamedMod.emplace(ModInst->getModuleName(), ModInst);
90
    // Link the module instance to this store manager.
91
0
    (const_cast<Instance::ModuleInstance *>(ModInst))
92
0
        ->linkStore(this, [](StoreManager *Store,
93
0
                             const Instance::ModuleInstance *Inst) {
94
          // The unlink callback.
95
0
          std::unique_lock CallbackLock(Store->Mutex);
96
0
          (Store->NamedMod).erase(std::string(Inst->getModuleName()));
97
0
        });
98
0
    return {};
99
0
  }
100
101
  /// Unregister a named module from this store.
102
0
  Expect<void> unregisterModule(std::string_view Name) {
103
0
    std::unique_lock Lock(Mutex);
104
0
    auto Iter = NamedMod.find(Name);
105
0
    if (Iter == NamedMod.cend()) {
106
0
      return Unexpect(ErrCode::Value::UnknownImport);
107
0
    }
108
0
    (const_cast<Instance::ModuleInstance *>(Iter->second))->unlinkStore(this);
109
0
    NamedMod.erase(Iter);
110
0
    return {};
111
0
  }
112
113
  void addNamedModule(std::string_view Name,
114
0
                      const Instance::ModuleInstance *Inst) {
115
0
    std::unique_lock Lock(Mutex);
116
0
    SoftNamedMod.emplace(Name, Inst);
117
0
  }
118
119
  Expect<void> registerComponent(std::string_view Name,
120
0
                                 const Instance::ComponentInstance *Inst) {
121
0
    std::unique_lock Lock(Mutex);
122
0
    auto Iter = NamedComp.find(Name);
123
0
    if (likely(Iter != NamedComp.cend())) {
124
0
      return Unexpect(ErrCode::Value::ModuleNameConflict);
125
0
    }
126
0
    NamedComp.emplace(Name, Inst);
127
0
    return {};
128
0
  }
129
0
  Expect<void> registerComponent(const Instance::ComponentInstance *Inst) {
130
0
    return registerComponent(Inst->getComponentName(), Inst);
131
0
  }
132
133
private:
134
  /// \name Mutex for thread-safe.
135
  mutable std::shared_mutex Mutex;
136
137
  friend class Executor::Executor;
138
139
  /// Collect the instantiation failed module.
140
0
  void recycleModule(std::unique_ptr<Instance::ModuleInstance> &&Mod) {
141
0
    FailedMod = std::move(Mod);
142
0
  }
143
144
  /// \name Module name mapping.
145
  std::map<std::string, const Instance::ModuleInstance *, std::less<>> NamedMod;
146
  /// \name Soft module are those temporary added by component linking process
147
  std::map<std::string, const Instance::ModuleInstance *, std::less<>>
148
      SoftNamedMod;
149
  std::map<std::string, const Instance::ComponentInstance *, std::less<>>
150
      NamedComp;
151
152
  /// \name Last instantiation failed module.
153
  /// According to the current spec, the instances should be able to be
154
  /// referenced even if instantiation failed. Therefore store the failed module
155
  /// instance here to keep the instances.
156
  /// FIXME: Is this necessary to be a vector?
157
  std::unique_ptr<Instance::ModuleInstance> FailedMod;
158
};
159
160
} // namespace Runtime
161
} // namespace WasmEdge