// Get the value associated with the given key. // 1. If the key is not in the trie, return nullptr. // 2. If the key is in the trie but the type is mismatched, return nullptr. // 3. Otherwise, return the value. template <classT> autoTrie::Get(std::string_view key)const -> const T * { if (!root_) { returnnullptr; } std::shared_ptr<const TrieNode> ptr(root_); for (char ch : key) { if (ptr->children_.count(ch) == 0) { returnnullptr; } ptr = ptr->children_.at(ch); } if (!ptr->is_value_node_) { returnnullptr; } auto p = std::dynamic_pointer_cast<const TrieNodeWithValue<T>>(ptr); if (!p) { returnnullptr; } return p->value_.get(); }
template <classT> autoTrie::Put(std::string_view key, T value)const -> Trie { // Note that `T` might be a non-copyable type. Always use `std::move` when creating `shared_ptr` on that value.
// You should walk through the trie and create new nodes if necessary. If the node corresponding to the key already // exists, you should create a new `TrieNodeWithValue`. std::shared_ptr<const TrieNode> new_root(nullptr); std::map<char, std::shared_ptr<const TrieNode>> children; if (key.length() == 0) {//key长度为0,表示在root节点put value if (root_) { children = root_->children_; } new_root = std::make_shared<const TrieNodeWithValue<T>>(children, std::make_shared<T>(std::move(value)));//创建一个新的root节点 returnTrie(new_root); }
template <classT> autoTrieStore::Get(std::string_view key) -> std::optional<ValueGuard<T>> { // Pseudo-code: // (1) Take the root lock, get the root, and release the root lock. Don't lookup the value in the // trie while holding the root lock. // (2) Lookup the value in the trie. // (3) If the value is found, return a ValueGuard object that holds a reference to the value and the // root. Otherwise, return std::nullopt. Trie root; { std::lock_guard<std::mutex> guard(root_lock_); root = root_; } const T *val = root.Get<T>(key); if (!val) { return std::nullopt; }
template <classT> voidTrieStore::Put(std::string_view key, T value){ // You will need to ensure there is only one writer at a time. Think of how you can achieve this. // The logic should be somehow similar to `TrieStore::Get`. std::lock_guard<std::mutex> guard(write_lock_); Trie root; { std::lock_guard<std::mutex> guard1(root_lock_); root = root_; }
voidTrieStore::Remove(std::string_view key){ // You will need to ensure there is only one writer at a time. Think of how you can achieve this. // The logic should be somehow similar to `TrieStore::Get`. std::lock_guard<std::mutex> guard(write_lock_); Trie root; { std::lock_guard<std::mutex> guard1(root_lock_); root = root_; }