Add Closer, partial RAII class
Closer is a template using which C-style resources can be managed in a C++ context where exceptions can occur. By placing a C resource in a Closer instance, it is certain the resource will be freed when the closing scope is exited irrespective of whether that occurs due to the normal control flow, due to a return statement or an exception having been thrown. To be used with Closer, the CloserTraits template must be specialized for the type in question. With this change specializations are provided for FILE*, json_t*, pcre_code* and pcre2_match_data*.
This commit is contained in:
parent
482fbe6400
commit
0b4c379539
16
include/maxscale/jansson.h
Normal file
16
include/maxscale/jansson.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
#include <jansson.h>
|
44
include/maxscale/jansson.hh
Normal file
44
include/maxscale/jansson.hh
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <maxscale/jansson.h>
|
||||
#include <maxscale/utils.hh>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
/**
|
||||
* @class CloserTraits<json_t*> jansson.hh <maxscale/jansson.hh>
|
||||
*
|
||||
* Specialization of @c CloserTraits for @c json_t*.
|
||||
*/
|
||||
template<>
|
||||
struct CloserTraits<json_t*>
|
||||
{
|
||||
static void close_if(json_t* pJson)
|
||||
{
|
||||
if (pJson)
|
||||
{
|
||||
json_decref(pJson);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset(json_t*& pJson)
|
||||
{
|
||||
pJson = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
66
include/maxscale/pcre2.hh
Normal file
66
include/maxscale/pcre2.hh
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <maxscale/pcre2.h>
|
||||
#include <maxscale/utils.hh>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
/**
|
||||
* @class CloserTraits<pcre2_code*> pcre2.hh <maxscale/pcre2.hh>
|
||||
*
|
||||
* Specialization of @c CloserTraits for @c pcre2_code*.
|
||||
*/
|
||||
template<>
|
||||
struct CloserTraits<pcre2_code*>
|
||||
{
|
||||
static void close_if(pcre2_code* pCode)
|
||||
{
|
||||
if (pCode)
|
||||
{
|
||||
pcre2_code_free(pCode);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset(pcre2_code*& pCode)
|
||||
{
|
||||
pCode = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class CloserTraits<pcre2_match_data*> pcre2.hh <maxscale/pcre2.hh>
|
||||
*
|
||||
* Specialization of @c CloserTraits for @c pcre2_match_data*.
|
||||
*/
|
||||
template<>
|
||||
struct CloserTraits<pcre2_match_data*>
|
||||
{
|
||||
static void close_if(pcre2_match_data* pData)
|
||||
{
|
||||
if (pData)
|
||||
{
|
||||
pcre2_match_data_free(pData);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset(pcre2_match_data*& pData)
|
||||
{
|
||||
pData = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
180
include/maxscale/utils.hh
Normal file
180
include/maxscale/utils.hh
Normal file
@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
/**
|
||||
* @class CloserTraits utils.hh <maxscale/utils.hh>
|
||||
*
|
||||
* A traits class used by Closer. To be specialized for all types that are
|
||||
* used with Closer.
|
||||
*/
|
||||
template<class T>
|
||||
struct CloserTraits
|
||||
{
|
||||
/**
|
||||
* Closes/frees/destroys a resource.
|
||||
*
|
||||
* @param t Close the resource *if* it has not been closed already.
|
||||
*/
|
||||
static void close_if(T t);
|
||||
|
||||
/**
|
||||
* Resets a reference to a resource. After the call, the value of t should
|
||||
* be such that @c close_if can recognize that the reference already has
|
||||
* been closed.
|
||||
*
|
||||
* @param t Reference to a resource.
|
||||
*/
|
||||
static void reset(T& t);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Closer utils.hh <maxscale/utils.hh>
|
||||
*
|
||||
* The template class Closer is a class that is intended to be used
|
||||
* for ensuring that a C style resource is released at the end of a
|
||||
* scoped block, irrespective of how that block is exited (by reaching
|
||||
* the end of it, or by a return or exception in the middle of it).
|
||||
*
|
||||
* Closer performs the actual resource releasing using CloserTraits
|
||||
* that need to be specialized for every type of resource to be managed.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* void f()
|
||||
* {
|
||||
* FILE* pFile = fopen(...);
|
||||
*
|
||||
* if (pFile)
|
||||
* {
|
||||
* Closer<FILE*> file(pFile);
|
||||
*
|
||||
* // Use pFile, call functions that potentually may throw
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Without @c Closer all code would have to be placed within try/catch
|
||||
* blocks, which quickly becomes unwieldy as the number of managed
|
||||
* resources grows.
|
||||
*/
|
||||
template<class T>
|
||||
class Closer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates the closer and stores the provided resourece. Note that
|
||||
* the constructor assumes that the resource exists already.
|
||||
*
|
||||
* @param resource The resource whose closing is to be ensured.
|
||||
*/
|
||||
Closer(T resource)
|
||||
: m_resource(resource)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the closer and releases the resource.
|
||||
*/
|
||||
~Closer()
|
||||
{
|
||||
CloserTraits<T>::close_if(m_resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original resource. Note that the ownership of the
|
||||
* resource remains with the closer.
|
||||
*
|
||||
* @return The resource that was provided in the constructor.
|
||||
*/
|
||||
T get() const
|
||||
{
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the closer, that is, releases the resource.
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
CloserTraits<T>::close_if(m_resource);
|
||||
CloserTraits<T>::reset(m_resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the closer, that is, releases the resource and assigns a
|
||||
* new resource to it.
|
||||
*/
|
||||
void reset(T resource)
|
||||
{
|
||||
CloserTraits<T>::close_if(m_resource);
|
||||
m_resource = resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original resource together with its ownership. That is,
|
||||
* after this call the responsibility for releasing the resource belongs
|
||||
* to the caller.
|
||||
*
|
||||
* @return The resource that was provided in the constructor.
|
||||
*/
|
||||
T release()
|
||||
{
|
||||
T resource = m_resource;
|
||||
CloserTraits<T>::reset(m_resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
private:
|
||||
Closer(const Closer&);
|
||||
Closer& operator = (const Closer&);
|
||||
|
||||
private:
|
||||
T m_resource;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
/**
|
||||
* @class CloserTraits<FILE*> utils.hh <maxscale/utils.hh>
|
||||
*
|
||||
* Specialization of @c CloserTraits for @c FILE*.
|
||||
*/
|
||||
template<>
|
||||
struct CloserTraits<FILE*>
|
||||
{
|
||||
static void close_if(FILE* pFile)
|
||||
{
|
||||
if (pFile)
|
||||
{
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset(FILE*& pFile)
|
||||
{
|
||||
pFile = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user