Based on work trying to clean up Coverity issues, we have run in to pattern
that looks like this
X x = alloc_some_resource();
if (! cond1) { Log("error"); destroy(x); return FAIL; }
if (! cond2) { Log("error"); destroy(x); return FAIL; }
// ... etc ...
return x;
The problem is that frequently not every return case cleans up every resource
and so resources are leaked. There is an existing class, xptr, in
lib/ts/ink_memory.h which handles this for some cases. It is a container for a
single resource which cleans up the resource if the container goes out of
scope. That means any return will clean up the resource without having any
explicit code. In addition it permits the resource to be removed from the
container if it is needed after all of the contingent checks have been done.
The modified code would look like
scoped_X x = alloc_some_resource();
if (! cond1) { Log("error"); return FAIL; }
if (! cond2) { Log("error"); return FAIL; }
// ... etc ...
return x.release();
This is very handy when the checks are not nicely lined up like this but
convoluted and non-obvious.
The decision at the HackAThon was made that we should have a more general
version of this that (1) handled more types of resources and (2) had better
naming.
I have created issue TS-2943 to track this and have attached my proposed patch.
This creates a base implementation class and specialized subclasses for
specific resource types. This should allow easily extending this support for
other types as needed.
The base implementation class is scoped_resource<T,D> where T is the resource
type and D is a descriptor class that describes how to deal with a resource of
type T. From this I have built three more usable classes
ats_scoped_fd - holds a file descriptor, closes it if it goes out of scope.
ats_scoped_mem - holds a pointer to memory that is either an array or a class
instance, created by ats_malloc. ats_free is called on the pointer if the
container goes out of scope.
ats_scoped_obj - holds a pointer to a class instance created with new. delete
is called on the pointer if the container goes out of scope.
This is very similar to std::unique_ptr but unfortunately that is a C++
eleventy feature which we cannot, at this time, require.