File: MEM_alloc_string_storage.hh

package info (click to toggle)
blender 4.3.2%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 309,564 kB
  • sloc: cpp: 2,385,210; python: 330,236; ansic: 280,972; xml: 2,446; sh: 972; javascript: 317; makefile: 170
file content (118 lines) | stat: -rw-r--r-- 3,487 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* SPDX-FileCopyrightText: 2024 Blender Authors
 *
 * SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once

/** \file
 * \ingroup intern_memutil
 *
 * Implement a static storage for complex, non-static allocation strings passed MEM_guardedalloc
 * functions.
 */

#include <any>
#include <cassert>
#include <string>
#include <unordered_map>

namespace intern::memutil {

/**
 * A 'static' storage of allocation strings, with a simple API to set and retrieve them.
 *
 * This is a templated wrapper around a std::unordered_map, to allow custom key types.
 */
template<typename keyT, template<typename> typename hashT> class AllocStringStorage {
  std::unordered_map<keyT, std::string, hashT<keyT>> storage_;

 public:
  /**
   * Check whether the given key exists in the storage.
   *
   * \return `true` if the \a key is found in storage, false otherwise.
   */
  bool contains(const keyT &key)
  {
    return storage_.count(key) != 0;
  }

  /**
   * Return the alloc string for the given key in the storage.
   *
   * \return A pointer to the stored string if \a key is found, `nullptr` otherwise.
   */
  const char *find(const keyT &key)
  {
    if (storage_.count(key) != 0) {
      return storage_[key].c_str();
    }
    return nullptr;
  }

  /**
   * Insert the given alloc string in the storage, at the given key, and return a pointer
   * to the stored string.
   *
   * \param alloc_string: The alloc string to store at \a key.
   * \return A pointer to the inserted stored string.
   */
  const char *insert(const keyT &key, std::string alloc_string)
  {
#ifndef NDEBUG
    assert(storage_.count(key) == 0);
#endif
    return (storage_[key] = std::move(alloc_string)).c_str();
  }
};

namespace internal {

/**
 * The main container for all #AllocStringStorage.
 */
class AllocStringStorageContainer {
  std::unordered_map<std::string, std::any> storage_;

 public:
  /**
   * Create if necessary, and return the #AllocStringStorage for the given \a storage_identifier.
   *
   * The template arguments allow to define the type of key used for the mapping to allocation
   * strings.
   */
  template<typename keyT, template<typename> typename hashT>
  std::any &ensure_storage(const std::string &storage_identifier)
  {
    if (storage_.count(storage_identifier) == 0) {
      AllocStringStorage<keyT, hashT> storage_for_identifier;
      return (storage_[storage_identifier] = std::make_any<AllocStringStorage<keyT, hashT>>(
                  std::move(storage_for_identifier)));
    }
    return storage_[storage_identifier];
  }
};

/**
 * Ensure that the static AllocStringStorageContainer is defined and created, and return a
 * reference to it.
 */
AllocStringStorageContainer &ensure_storage_container();

}  // namespace internal

/**
 * Return a reference to the AllocStringStorage static data matching the given \a
 * storage_identifier, creating it if needed.
 *
 * \note The storage is `thread_local` data, so access to it is thread-safe as long as it is not
 * shared between threads by the user code.
 */
template<typename keyT, template<typename> typename hashT>
AllocStringStorage<keyT, hashT> &alloc_string_storage_get(const std::string &storage_identifier)
{
  internal::AllocStringStorageContainer &storage_container = internal::ensure_storage_container();
  std::any &storage = storage_container.ensure_storage<keyT, hashT>(storage_identifier);
  return std::any_cast<AllocStringStorage<keyT, hashT> &>(storage);
}

}  // namespace intern::memutil