-
Notifications
You must be signed in to change notification settings - Fork 0
Implementation Patterns
René Fonseca edited this page Feb 6, 2020
·
8 revisions
Description of common implementation patterns.
Use the compiler to ensure MT-safety for on-demand initialization of global resources.
Reference<Resource> create()
{
Reference<Resource> resource = new Resource();
// do something
if (gotError) {
return nullptr;
}
return resource;
}
Reference<Resource> getResource()
{
static Reference<Resource> resource = create(); // compiler will ensure MT-safety here
return resource;
}
ATTENTION: You should ensure that globals do not have cyclic dependencies. This can cause a runtime crash or deadlock.
Use an internal reference counted handle to avoid issues with copying by value. It is generally undesired to throw exceptions in destructors - so it is always good to have a way to avoid this possibility by providing a way to detach the handle before destruction. Similarly it is good to have the option to construct invalid handles and delay actual resource acquisition until a later time.
class Resource : public Object {
private:
class Handle : public ReferenceCountedObject {
};
Reference<Handle> handle;
public:
/** Could create resource or initialize as invalid. */
Resource();
/** Allow check if resource is valid if it can be explicitly closed. */
bool isValid() const;
/** Creates the resource. */
void open();
void useit();
/** Close handle. Impacts all usages. */
void close();
};
void doit()
{
Resource r1;
Resource r2 = r1; // fine since we use reference counting
r2.useit();
r2.close();
r1.useit(); // should fail since closed
r2.close(); // multiple closes should be allowed
}
When adding new resources, you should consider adding direct tracking support in the Profiler
also.