Skip to content
Snippets Groups Projects
Commit 08a133c6 authored by Erik von Reis's avatar Erik von Reis
Browse files

Merge branch 'pointer_cleanup_nds' into 'master'

NDS - replacing a gds based reference counting system with a smart pointer.

See merge request cds/advligorts!194
parents 0a9eece9 5ca81bf8
No related branches found
No related tags found
1 merge request!194NDS - replacing a gds based reference counting system with a smart pointer.
......@@ -40,7 +40,9 @@
#ifndef __CINT__
#include "mmap.hh"
#include "refcount.hh"
#include <memory>
#include "raii.hh"
namespace gdsbase
{
......@@ -69,13 +71,16 @@ namespace gdsbase
typedef const T& const_reference_type;
/// Size type
typedef mmap::size_type size_type;
/// Reference counter
typedef dynamic_ref_counter< mmap > ref_counter;
typedef std::unique_ptr<mmap> ref_pointer;
mmap_ptr(const mmap_ptr&) = delete;
mmap_ptr& operator=(const mmap_ptr&) = delete;
/** Creates a NULL pointer.
@memo Default constructor
******************************************************************/
mmap_ptr( ) : fMmap( 0 )
mmap_ptr( ) : fMmap( nullptr )
{
}
/** Creates an pointer and mappes it to a file.
......@@ -84,7 +89,7 @@ namespace gdsbase
mmap_ptr( const char* filename,
std::ios_base::openmode which = std::ios_base::in |
std::ios_base::out )
: fMmap( 0 )
: fMmap( nullptr )
{
set( filename, which );
}
......@@ -92,7 +97,7 @@ namespace gdsbase
Does not own the data!
@memo Constructor
******************************************************************/
mmap_ptr( pointer_type p, size_type len ) : fMmap( 0 )
mmap_ptr( pointer_type p, size_type len ) : fMmap( nullptr )
{
set( p, len );
}
......@@ -131,7 +136,7 @@ namespace gdsbase
pointer_type
get( )
{
return fMmap ? (pointer_type)fMmap->get( ) : 0;
return fMmap.get();
}
/** Get a pointer.
@memo Get
......@@ -139,15 +144,7 @@ namespace gdsbase
const_pointer_type
get( ) const
{
return fMmap ? (const_pointer_type)fMmap->get( ) : 0;
}
/** Get size.
@memo Get size
******************************************************************/
size_type
size( ) const
{
return fMmap ? fMmap->size( ) / element_size( ) : 0;
return fMmap.get();
}
/** Get element size.
@memo Get element size
......@@ -182,9 +179,7 @@ namespace gdsbase
void reset( );
private:
mmap* fMmap;
/// Reference count
ref_counter fCount;
ref_pointer fMmap;
};
//______________________________________________________________________________
......@@ -192,9 +187,8 @@ namespace gdsbase
inline bool
mmap_ptr< T >::set( const char* filename, std::ios_base::openmode which )
{
fMmap = new mmap( filename, which );
fCount = ref_counter( fMmap );
return get( ) != 0;
fMmap = raii::make_unique_ptr<mmap>(filename, which);
return true;
}
//______________________________________________________________________________
......@@ -202,10 +196,8 @@ namespace gdsbase
inline bool
mmap_ptr< T >::set( pointer_type p, size_type len )
{
fMmap =
new mmap( (gdsbase::mmap::pointer_type)p, len * element_size( ) );
fCount = ref_counter( fMmap );
return get( ) != 0;
fMmap = raii::make_unique_ptr<mmap>((gdsbase::mmap::pointer_type)p, len * element_size( ));
return true;
}
//______________________________________________________________________________
......@@ -213,11 +205,7 @@ namespace gdsbase
inline void
mmap_ptr< T >::reset( )
{
if ( fMmap )
{
fMmap = 0;
fCount = ref_counter( fMmap );
}
fMmap = nullptr;
}
} // namespace gdsbase
......
#ifndef RAII_HH
#define RAII_HH
#include <unistd.h>
#include <memory>
/**
* Some 'smart' resource wrappers using the raii technique.
* This should be cleaned up and foled into C++11 code as
* it becomes feasible.
*/
namespace raii
{
template < typename T >
class array_ptr
{
T* _p;
array_ptr( array_ptr< T >& other );
array_ptr< T > operator=( const array_ptr< T >& other );
void
clean_up( )
{
if ( _p )
delete[] _p;
_p = 0;
}
public:
array_ptr( T* p = 0 ) : _p( p )
{
}
~array_ptr( )
{
clean_up( );
}
T*
get( ) const
{
return _p;
}
void
reset( T* p )
{
if ( p != _p )
{
clean_up( );
_p == p;
}
}
T*
release( )
{
T* tmp( _p );
_p = 0;
return tmp;
}
};
template < typename T >
class lock_guard
{
lock_guard( lock_guard< T >& other );
lock_guard operator=( lock_guard< T >& other );
T& _m;
public:
lock_guard( T& m ) : _m( m )
{
_m.lock( );
}
~lock_guard( )
{
_m.unlock( );
}
};
template <>
class lock_guard< pthread_mutex_t >
{
lock_guard( lock_guard< pthread_mutex_t >& other );
lock_guard operator=( lock_guard< pthread_mutex_t > );
pthread_mutex_t& _m;
public:
lock_guard( pthread_mutex_t& m ) : _m( m )
{
pthread_mutex_lock( &_m );
}
~lock_guard( )
{
pthread_mutex_unlock( &_m );
}
};
class file_handle
{
int _fd;
file_handle( const file_handle& other );
file_handle operator=( const file_handle& other );
public:
file_handle( int fd ) : _fd( fd )
{
}
~file_handle( )
{
reset( );
}
int
get( ) const
{
return _fd;
}
int
release( )
{
int tmp = _fd;
_fd = -1;
return tmp;
}
void
reset( )
{
if ( _fd >= 0 )
{
::close( _fd );
_fd = -1;
}
}
};
// std::make_unique didn't make it into C++11, so
// to allow this to work in a pre C++14 world, we
// provide a simple replacement.
//
// A make_unique<> for C++11. Taken from
// "Effective Modern C++ by Scott Meyers (O'Reilly).
// Copyright 2015 Scott Meyers, 978-1-491-90399-5"
//
// Permission given in the book to reuse code segments.
//
// @tparam T The type of the object to be managed by the unique_ptr
// @tparam Ts The type of the arguments to T's constructor
// @param params The arguments to forward to the constructor
// @return a std::unique_ptr<T>
template < typename T, typename... Ts >
std::unique_ptr< T >
make_unique_ptr( Ts&&... params )
{
return std::unique_ptr< T >( new T( std::forward< Ts >( params )... ) );
}
} // namespace raii
#endif // RAII_HH
#ifndef _LIGO_REF_PTR_H
#define _LIGO_REF_PTR_H
/*----------------------------------------------------------------------*/
/* */
/* Module Name: ref_ptr */
/* */
/* Module Description: Smart pointer supporting reference counting */
/* */
/* Revision History: */
/* Rel Date Programmer Comments */
/* 0.1 27Nov01 D. Sigg First release */
/* */
/* Documentation References: */
/* Man Pages: ref_ptr.html */
/* References: none */
/* */
/* Author Information: */
/* Name Telephone Fax e-mail */
/* Daniel Sigg (509) 372-8132 (509) 372-8137 sigg_d@ligo.mit.edu */
/* */
/* */
/* ------------------- */
/* */
/* LIGO */
/* */
/* THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */
/* */
/* (C) The LIGO Project, 1999. */
/* */
/* */
/* Caltech MIT */
/* LIGO Project MS 51-33 LIGO Project NW-17 161 */
/* Pasadena CA 91125 Cambridge MA 01239 */
/* */
/* LIGO Hanford Observatory LIGO Livingston Observatory */
/* P.O. Box 1970 S9-02 19100 LIGO Lane Rd. */
/* Richland WA 99352 Livingston, LA 70754 */
/* */
/*----------------------------------------------------------------------*/
#include "refcount/refcount.hh"
#ifndef __CINT__
namespace gdsbase
{
/** @name Smart pointer which implements reference counting.
This pointer can be copied and used as an object for standard
containers. This smart pointer adopts the object and will free
it when the last pointer to it gets destroyed.
@memo Smart pointer with reference counting
@author Written November 2001 by Daniel Sigg
@version 1.0
************************************************************************/
template < class T >
class ref_ptr
{
public:
/// Value type
typedef T value_type;
/// Pointer type
typedef T* pointer_type;
/// Const pointer type
typedef const T* const_pointer_type;
/// Reference type
typedef T& reference_type;
/// Const reference type
typedef const T& const_reference_type;
/// Reference counter
typedef dynamic_ref_counter< T > ref_counter;
/** Creates a NULL pointer.
@memo Default constructor
******************************************************************/
ref_ptr( ) : fPtr( 0 )
{
}
/** Creates an pointer and adopts the object.
@memo Constructor
@param obj Object to be adopted
@param array Set true if array delete has to be used
******************************************************************/
explicit ref_ptr( T* obj, bool array = false ) : fPtr( 0 )
{
reset( obj, array );
}
/** Dereference operator.
@memo Dereference oprator
******************************************************************/
reference_type operator*( )
{
return *get( );
}
/** Dereference operator.
@memo Dereference oprator
******************************************************************/
const_reference_type operator*( ) const
{
return *get( );
}
/** Member access oprator.
@memo Member access oprator
******************************************************************/
pointer_type operator->( )
{
return get( );
}
/** Member access oprator.
@memo Member access oprator
******************************************************************/
const_pointer_type operator->( ) const
{
return get( );
}
/** Get a pointer.
@memo Get
******************************************************************/
pointer_type
get( )
{
return fPtr;
}
/** Get a pointer.
@memo Get
******************************************************************/
const_pointer_type
get( ) const
{
return fPtr;
}
/** Set pointer.
@memo Reset
******************************************************************/
void
reset( T* obj = 0, bool array = false )
{
fPtr = obj;
fCount = ref_counter( obj, array );
}
private:
/// Pointer to object
T* fPtr;
/// Reference count
ref_counter fCount;
};
} // namespace gdsbase
#endif // __CINT__
#endif // _LIGO_REF_PTR_H
#ifndef _LIGO_REFCOUNT_H
#define _LIGO_REFCOUNT_H
/*----------------------------------------------------------------------*/
/* */
/* Module Name: refcount */
/* */
/* Module Description: Helper class for reference counting */
/* */
/* Revision History: */
/* Rel Date Programmer Comments */
/* 0.1 3Mar01 D. Sigg First release */
/* */
/* Documentation References: */
/* Man Pages: refcount.html */
/* References: none */
/* */
/* Author Information: */
/* Name Telephone Fax e-mail */
/* Daniel Sigg (509) 372-8132 (509) 372-8137 sigg_d@ligo.mit.edu */
/* */
/* */
/* ------------------- */
/* */
/* LIGO */
/* */
/* THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */
/* */
/* (C) The LIGO Project, 1999. */
/* */
/* */
/* Caltech MIT */
/* LIGO Project MS 51-33 LIGO Project NW-17 161 */
/* Pasadena CA 91125 Cambridge MA 01239 */
/* */
/* LIGO Hanford Observatory LIGO Livingston Observatory */
/* P.O. Box 1970 S9-02 19100 LIGO Lane Rd. */
/* Richland WA 99352 Livingston, LA 70754 */
/* */
/*----------------------------------------------------------------------*/
#include "gmutex.hh"
namespace gdsbase
{
/** @name Helper class for reference counting.
@memo Helper class for reference counting
@author Written April 2001 by Daniel Sigg
@version 1.0
************************************************************************/
//@{
/** A templated reference counter. The counter maintains a count value
and a pointer to a parent class. The counter value is initialized
with zero and can be increased and decreased with the corresponding
operators. If the reference counter reaches zero, the parant class
will be deleted. A static reference counter can not be copied.
A static refernce counter is MT safe in the sense that it protects
its refernce counter. However, it will not protect the parent
class. Since the static_ref_counter is derived from the mutex
object, it can be used to protect the parent class. To avoid
deadlock it must not be locked during increasing or decreasing its
count value.
Example:
\begin{verbatim}
// one_resource is a sharable resource which implements
// reference counting.
class one_resource {
static_ref_count<one_resource> fRef;
public:
one_resource() : fRef (this) {++fRef; }
bool refInc() {retrun fRef.Increase(); }
bool refDec() {retrun fRef.Decrease(); }
void modify() {
thread::semlock (fRef); // use it as mutex
... }
...
};
// Since one-resource deleted itself when the refercnce count reaches
// zero, it has to be created with the new operator. In most cases it
// is probably better to use a dynamic refernce counter.
\end{verbatim}
@memo static reference counter.
************************************************************************/
template < class T >
class static_ref_counter : public thread::mutex
{
public:
/// Parent class type
typedef T class_type;
/// Make a reference counter
explicit static_ref_counter( T* parent = 0, bool array = false )
: fParent( parent ), fArray( array ), fCount( 0 )
{
}
/// Get the reference count
int
getCount( ) const
{
return fCount;
}
/// Set the reference count
void
setCount( int count )
{
fCount = count;
}
/// Get the parent class
T*
getParent( ) const
{
return fParent;
}
/// Set the parent class
void
setParent( T* parent, bool array = false )
{
fParent = parent;
fArray = array;
}
/// increase the reference count (prefix)
static_ref_counter&
operator++( )
{
increase( );
return *this;
}
/// increase the reference count (postfix)
static_ref_counter&
operator++( int )
{
increase( );
return *this;
}
/// decrease the reference count (prefix); deletes parant if reaches
/// zero
static_ref_counter&
operator--( )
{
decrease( );
return *this;
}
/// decrease the reference count (postfix); deletes parant if reaches
/// zero
static_ref_counter&
operator--( int )
{
decrease( );
return *this;
}
/// increase (returns true if counter value is positive)
bool
increase( )
{
thread::semlock( *this );
return ( ++fCount > 0 );
}
/// decrease (returns true if deleted)
bool
decrease( )
{
thread::semlock( *this );
if ( ( fCount > 0 ) && ( --fCount == 0 ) && fParent )
{
reset( );
return true;
}
else
return false;
}
/// dereference operator (returns parent)
T& operator*( ) const
{
return *fParent;
}
/// member access operator (returns parent)
T* operator->( ) const
{
return fParent;
}
private:
/// Parent class
T* fParent;
/// Parent is array?
bool fArray;
/// Counter
int fCount;
/// deletes the parent object
void
reset( )
{
if ( fArray )
delete[] fParent;
else
delete fParent;
fParent = 0;
}
/// No copy constructor
static_ref_counter( const static_ref_counter& );
/// No assignment operator
static_ref_counter& operator=( const static_ref_counter& );
};
/** A templated reference counter. This counter maintains a pointer to
a static reference counter. The counter value is initialized
with one and is increased everytime the counter is copied and
decreased everytime the counter is destroyed.
Example:
\begin{verbatim}
// class which manages a shared floating point array
class container {
float* fData; // must be before reference counter!
dynamic_ref_counter<float> fRef;
public:
container (int size)
: fData (new float[size]), fRef (fData, true) {}
...
};
// This is all what is needed to implement reference counting on
// the data array. The user does not have to implement a
// destructor, a copy costructor nor assignment operator.
// Because of the reference counter, the above example class
// implements a "shared" copy paradigm and destroyes the
// data automatically when no longer needed.
\end{verbatim}
@memo dynamic reference counter.
************************************************************************/
template < class T >
class dynamic_ref_counter
{
public:
/// Parent class type
typedef T class_type;
/// Static reference counter
typedef static_ref_counter< T > counter_type;
/// Get the reference count
int
getCount( ) const
{
return ( fCounter ) ? fCounter->getCount( ) : -1;
}
// Set the reference count
// void setCount (int count) {
// if (fCounter) fCounter->setCount (count); }
/// Get the parent class
T*
getParent( ) const
{
return ( fCounter ) ? fCounter->getParent( ) : 0;
}
/// Set the parent class
void
setParent( T* parent, bool array = false )
{
if ( fCounter )
fCounter->setParent( parent, array );
}
/// Constructor
explicit dynamic_ref_counter( T* parent = 0, bool array = false )
: fCounter( new counter_type( parent, array ) )
{
fCounter->increase( );
}
/// Destructor
~dynamic_ref_counter( )
{
if ( fCounter && fCounter->decrease( ) )
delete fCounter;
}
/// Copy constructor
dynamic_ref_counter( const dynamic_ref_counter& dref ) : fCounter( 0 )
{
*this = dref;
}
/// Copy constructor (from a static reference counter)
dynamic_ref_counter( counter_type* sref ) : fCounter( sref )
{
if ( fCounter )
fCounter->increase( );
}
/// Assignment operator
dynamic_ref_counter&
operator=( const dynamic_ref_counter& dref )
{
if ( this != &dref )
{
if ( fCounter && fCounter->decrease( ) )
delete fCounter;
fCounter = dref.fCounter;
if ( fCounter )
fCounter->increase( );
}
return *this;
}
/// Assignment operator (from a static reference counter)
dynamic_ref_counter&
operator=( counter_type* sref )
{
if ( fCounter && fCounter->decrease( ) )
delete fCounter;
fCounter = sref;
if ( fCounter )
fCounter->increase( );
return *this;
}
/// dereference operator (returns parent)
T& operator*( ) const
{
return *fCounter->getParent( );
}
/// member access operator (returns parent)
T* operator->( ) const
{
return fCounter->getParent( );
}
private:
/// Pointer to static reference counter
counter_type* fCounter;
};
//@}
} // namespace gdsbase
#endif // _LIGO_REFCOUNT_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment