comparison base/ById.h @ 1764:0678bf772f82 by-id

Doc
author Chris Cannam
date Wed, 17 Jul 2019 12:57:33 +0100
parents d954dfccd922
children 7faa08747f5e
comparison
equal deleted inserted replaced
1763:d1e2062cbdec 1764:0678bf772f82
25 #include <QMutex> 25 #include <QMutex>
26 #include <QString> 26 #include <QString>
27 27
28 #include "XmlExportable.h" 28 #include "XmlExportable.h"
29 29
30 //!!! todo: docs 30 /*
31 31 * ById - central pool of objects to be retrieved by persistent id.
32 //!!! further possibilities: 32 *
33 // 33 * This is a pretty simple mechanism for obtaining safe "borrowed"
34 // - get() returns a pointer wrapper that cannot be shared/copied 34 * references to shared objects, including across threads, based on an
35 // again by the caller (except by the usual C++ trickery) 35 * object ID.
36 // 36 *
37 // also to do: review how often we are calling getAs<...> when we 37 * A class (call it C) inherits WithTypedId<C>. This produces a type
38 // could just be using get 38 * C::Id containing a numerical id. Each instance of C (or subclass
39 39 * thereof) has an internal id of type C::Id whose value is unique
40 //!!! NB we still haven't solved the problem of what to do for a 40 * among all ids ever possessed by any instances of all classes that
41 //!!! user-initiated cancel of a transform 41 * use this id mechanism (within a single run of the program).
42 *
43 * Then we have a static store of type TypedById<C, C::Id>. This holds
44 * a set of heap-allocated C objects (or subclass thereof) and hands
45 * out shared_ptr references to them when queried by id. The
46 * application calls add() to pass an object to the store (which takes
47 * ownership of it), and the application calls release() when it
48 * thinks it has finished with an object, to request the store to
49 * delete it.
50 *
51 * Note that an object's id can't (without shenanigans) be queried
52 * directly from that object - it is returned when the object is added
53 * to a ById store. So if you have an object id, you know that the
54 * object must have been added to a store at some point.
55 *
56 * The goal is to improve code that would previously have retained a
57 * bare pointer to a heap-allocated object that it did not own. For
58 * example, in Sonic Visualiser we have a Model hierarchy of complex
59 * mutable objects, and any given model may be referred to by many
60 * different layers, transforms (as both source and target) etc. Using
61 * bare pointers for those references means that we need everything to
62 * be notified (and act properly on the notification) if a model is
63 * about to be deleted. Using a Model::Id instead gives the code a
64 * guarantee: if the model has been deleted since you last looked at
65 * it, then the ById store will return a null shared_ptr from its
66 * get() function for that id; but if it returns a non-null
67 * shared_ptr, then the object being pointed to can't be deleted while
68 * that shared_ptr is in scope.
69 *
70 * Example:
71 *
72 * class Thing : public WithTypedId<Thing> { Thing(int x) { } };
73 * typedef TypedById<Thing, Thing::Id> ThingById;
74 *
75 * // application creates a new Thing
76 * // ...
77 * auto thing = std::make_shared<Thing>(10);
78 * auto thingId = ThingById::add(thing);
79 *
80 * // application then passes thingId to something else, without
81 * // storing the shared_ptr anywhere - the ById store manages that
82 *
83 * // code elsewhere now has the thingId, and needs to use the Thing
84 * // ...
85 * void doSomething() {
86 * auto thing = ThingById::get(m_thingId);
87 * if (!thing) { // the Thing has been deleted, stop acting on it
88 * return; // (this may be an error or it may be unexceptional)
89 * }
90 * // now we have a guarantee that the thing ptr will be valid
91 * // until it goes out of scope when doSomething returns
92 * }
93 *
94 * // application wants to be rid of the Thing
95 * ThingById::release(thingId);
96 */
97
98 //!!! to do: review how often we are calling getAs<...> when we could
99 // just be using get
42 100
43 struct IdAlloc { 101 struct IdAlloc {
44 102
45 // The value NO_ID (-1) is never allocated 103 // The value NO_ID (-1) is never allocated
46 static const int NO_ID = -1; 104 static const int NO_ID = -1;