Coverage Report

Created: 2025-07-01 06:18

/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
  void addNamedModule(std::string_view Name,
102
0
                      const Instance::ModuleInstance *Inst) {
103
0
    std::unique_lock Lock(Mutex);
104
0
    SoftNamedMod.emplace(Name, Inst);
105
0
  }
106
107
  Expect<void> registerComponent(std::string_view Name,
108
0
                                 const Instance::ComponentInstance *Inst) {
109
0
    std::unique_lock Lock(Mutex);
110
0
    auto Iter = NamedComp.find(Name);
111
0
    if (likely(Iter != NamedComp.cend())) {
112
0
      return Unexpect(ErrCode::Value::ModuleNameConflict);
113
0
    }
114
0
    NamedComp.emplace(Name, Inst);
115
0
    return {};
116
0
  }
117
0
  Expect<void> registerComponent(const Instance::ComponentInstance *Inst) {
118
0
    return registerComponent(Inst->getComponentName(), Inst);
119
0
  }
120
121
private:
122
  /// \name Mutex for thread-safe.
123
  mutable std::shared_mutex Mutex;
124
125
  friend class Executor::Executor;
126
127
  /// Collect the instantiation failed module.
128
0
  void recycleModule(std::unique_ptr<Instance::ModuleInstance> &&Mod) {
129
0
    FailedMod = std::move(Mod);
130
0
  }
131
132
  /// \name Module name mapping.
133
  std::map<std::string, const Instance::ModuleInstance *, std::less<>> NamedMod;
134
  /// \name Soft module are those temporary added by component linking process
135
  std::map<std::string, const Instance::ModuleInstance *, std::less<>>
136
      SoftNamedMod;
137
  std::map<std::string, const Instance::ComponentInstance *, std::less<>>
138
      NamedComp;
139
140
  /// \name Last instantiation failed module.
141
  /// According to the current spec, the instances should be able to be
142
  /// referenced even if instantiation failed. Therefore store the failed module
143
  /// instance here to keep the instances.
144
  /// FIXME: Is this necessary to be a vector?
145
  std::unique_ptr<Instance::ModuleInstance> FailedMod;
146
};
147
148
} // namespace Runtime
149
} // namespace WasmEdge