Cantera  3.2.0a4
Loading...
Searching...
No Matches
Cabinet.h
Go to the documentation of this file.
1/**
2 * @file Cabinet.h
3 */
4
5// This file is part of Cantera. See License.txt in the top-level directory or
6// at https://cantera.org/license.txt for license and copyright information.
7
8#ifndef CT_CABINET_H
9#define CT_CABINET_H
10
13#include <unordered_map>
14
15namespace Cantera {
16
17/**
18 * Template for classes to hold pointers to objects. The Cabinet<M> class
19 * maintains a list of pointers to objects of class M (or of subclasses of M). These
20 * classes are used by the 'CLib' interface library functions that provide access to
21 * %Cantera C++ objects from outside C++. To refer to an existing object, the library
22 * functions take an integer argument that specifies the location in the pointer list
23 * maintained by the appropriate Cabinet<M> instance. The pointer is retrieved
24 * from the list by the interface function, the desired method is invoked, and the
25 * result returned to the non-C++ calling procedure. By storing the pointers in a
26 * Cabinet, there is no need to encode them in a string or integer and pass
27 * them out to the non-C++ calling routine, as some other interfacing schemes do.
28 *
29 * The Cabinet<M> class can be used to store pointers to arbitrary objects. In
30 * most cases, class M is a base class with virtual methods, and the base class versions
31 * of the methods throw CanteraError exceptions. The subclasses overload these methods
32 * to implement the desired functionality. Class Cabinet<M> stores only the
33 * base-class pointers, but since the methods are virtual, the method of the appropriate
34 * subclass will be invoked.
35 *
36 * As the Cabinet<M> class uses smart pointers, it is set up to allow deleting
37 * objects in an inherently safe manner. Method 'del' does the following. If called
38 * with n >= 0, it dereferences the object. The original object is only destroyed if the
39 * reference is not shared by other objects. In this way, if it is deleted again
40 * inadvertently nothing happens, and if an attempt is made to reference the object by
41 * its index number, a standard exception is thrown.
42 *
43 * The Cabinet<M> class is implemented as a singleton. The constructor is never
44 * explicitly called; instead, static function Cabinet<M>::Cabinet() is
45 * called to obtain a pointer to the instance. This function calls the constructor on
46 * the first call and stores the pointer to this instance. Subsequent calls simply
47 * return the already-created pointer.
48 */
49template<class M>
51{
52public:
53 typedef vector<shared_ptr<M>>& dataRef;
54 typedef std::unordered_map<const M*, set<int>>& lookupRef;
55
56 /**
57 * Constructor.
58 */
60
61 /**
62 * Add a new object. The index of the object is returned.
63 */
64 static int add(shared_ptr<M> obj) {
65 dataRef data = getData();
66 data.push_back(obj);
67 int idx = static_cast<int>(data.size()) - 1;
68 lookupRef lookup = getLookup();
69 if (lookup.count(obj.get())) {
70 lookup[obj.get()].insert(idx);
71 } else {
72 lookup[obj.get()] = {idx};
73 }
74 return idx;
75 }
76
77 /**
78 * Return cabinet size.
79 */
80 static int size() {
81 return static_cast<int>(getData().size());
82 }
83
84 /**
85 * Delete all objects and erase mapping.
86 */
87 static int reset() {
88 getData().clear();
89 getLookup().clear();
90 return 0;
91 }
92
93 /**
94 * Delete the nth object.
95 */
96 static void del(int n) {
97 dataRef data = getData();
98 if (n >= 0 && n < len(data)) {
99 lookupRef lookup = getLookup();
100 if (!lookup.count(data[n].get())) {
101 throw CanteraError("Cabinet::del",
102 "Lookup table does not contain reference to object.");
103 }
104 if (lookup[data[n].get()].size() == 1) {
105 // set only contains one index
106 lookup.erase(data[n].get());
107 } else {
108 // remove index n from the reverse lookup table
109 lookup[data[n].get()].erase(n);
110 }
111 data[n].reset();
112 } else {
113 throw CanteraError("Cabinet::del",
114 "Attempt made to delete a non-existing object.");
115 }
116 }
117
118 /**
119 * Return a shared pointer to object n.
120 */
121 static shared_ptr<M>& at(int n) {
122 dataRef data = getData();
123 if (n < 0 || n >= len(data)) {
124 throw CanteraError("Cabinet::at", "Index {} out of range.", n);
125 }
126 if (!data[n]) {
127 throw CanteraError("Cabinet::at",
128 "Object with index {} has been deleted.", n);
129 }
130 return data[n];
131 }
132
133 /**
134 * Return object n, cast to the specified type.
135 */
136 template <class T>
137 static shared_ptr<T> as(int n) {
138 auto obj = std::dynamic_pointer_cast<T>(at(n));
139 if (obj) {
140 return obj;
141 }
142 throw CanteraError("Cabinet::as", "Item is not of the correct type.");
143 }
144
145private:
146 /**
147 * Static function that returns a pointer to the data member of
148 * the singleton Cabinet<M> instance. All member functions should
149 * access the data through this function.
150 */
151 static dataRef getData() {
152 if (s_storage == nullptr) {
153 s_storage = new Cabinet<M>();
154 }
155 return s_storage->m_table;
156 }
157
158 /**
159 * Static function that returns a pointer to the reverse lookup table of
160 * the singleton Cabinet<M> instance. All member functions should
161 * access the lookup table through this function.
162 */
163 static lookupRef getLookup() {
164 if (s_storage == nullptr) {
165 s_storage = new Cabinet<M>();
166 }
167 return s_storage->m_lookup;
168 }
169
170 /**
171 * Pointer to the single instance of this class.
172 */
174
175 /**
176 * Reverse lookup table for the single instance of this class.
177 */
178 std::unordered_map<const M*, set<int>> m_lookup;
179
180 /**
181 * List to hold pointers to objects.
182 */
183 vector<shared_ptr<M>> m_table;
184};
185
186}
187
188#endif
Template for classes to hold pointers to objects.
Definition Cabinet.h:51
static lookupRef getLookup()
Static function that returns a pointer to the reverse lookup table of the singleton Cabinet<M> instan...
Definition Cabinet.h:163
static Cabinet< M > * s_storage
Pointer to the single instance of this class.
Definition Cabinet.h:173
static shared_ptr< M > & at(int n)
Return a shared pointer to object n.
Definition Cabinet.h:121
static int reset()
Delete all objects and erase mapping.
Definition Cabinet.h:87
std::unordered_map< const M *, set< int > > m_lookup
Reverse lookup table for the single instance of this class.
Definition Cabinet.h:178
static void del(int n)
Delete the nth object.
Definition Cabinet.h:96
Cabinet()
Constructor.
Definition Cabinet.h:59
static int add(shared_ptr< M > obj)
Add a new object.
Definition Cabinet.h:64
static dataRef getData()
Static function that returns a pointer to the data member of the singleton Cabinet<M> instance.
Definition Cabinet.h:151
static shared_ptr< T > as(int n)
Return object n, cast to the specified type.
Definition Cabinet.h:137
static int size()
Return cabinet size.
Definition Cabinet.h:80
vector< shared_ptr< M > > m_table
List to hold pointers to objects.
Definition Cabinet.h:183
Base class for exceptions thrown by Cantera classes.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
U len(const T &container)
Get the size of a container, cast to a signed integer type.
Definition utilities.h:198
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...