/** @file
$Id$
$Date$
$Author$
@copy © Marc Wäckerlin
@license LGPL, see file COPYING
$Log$
Revision 1.6 2004/10/11 16:48:29 marc
better comment and operators -> and * for AutoPtr
Revision 1.5 2004/10/11 16:05:02 marc
new AutoPtr
Revision 1.4 2004/10/07 09:24:08 marc
enhance windoze compatibility
Revision 1.3 2004/08/28 16:21:25 marc
mrw-c++-0.92 (mrw)
- new file: version.cpp
- new file header for all sources
- work around warning in mrw::auto
- possibility to compile without log4cxx
- work around bugs in demangle.h and libiberty.h
- corrections in documentation
- added simple tracing mechanism
- more warnings
- small corrections in Auto<>::Free and a new test for it
- possibility to compile without stack trace
*/
#ifndef __MRW_AUTO_HPP__
#define __MRW_AUTO_HPP__
#include // size_t
#include // munmap, PROT_READ, MAP_SHARED
#include // close
#include
// forward
class bfd;
extern "C" int bfd_close(bfd*);
namespace mrw {
/** @defgroup AutoTools Classes for Automated Resource Handling
For pointers that have been allocated with @c new, you can use
std::auto_ptr to automatically free them when you leave the
context. Unfortunately there is no such thing for @c malloc
(except @c malloca that only works for a subset of problems: if
you and not a system call allocates memory), @c open and so on.
These classes can take over the resource ownership.
*/
//@{
/** @brief Automatically frees a resource when destructed.
@pre #include
AutoResource works exactly like std::auto_ptr, but for any
resource instead of new allocated pointers. Whenever the context
of AutoResource is left, the resource is freed by a call to the
given function. This way, resources are freed even in case of
exceptions.
Declare an automated file descriptor handler, a BFD handler and
a @c malloc-/ @c free handler (all these typedefs are already
part of the library):
@code
typedef mrw::AutoResource AutoFile;
typedef mrw::AutoResource AutoBfd;
template class Auto {
public:
typedef mrw::AutoResource Free;
};
@endcode
@param RESOURCE_TYPE type of the resource to manage
@param FUNCTION_PTR type of the function that frees the resource
@param FREE_FUNCTION the function that frees the resource
@param INITIAL_VALUE_TYPE type of the initial value
(pointers may have to be initialized by an integer)
@param INITIAL_VALUE value when the resource is unassigned
@param FREE_TYPE type to free, if cast is needed
*/
template
class AutoResource {
public:
/// @brief Construct from an allocated resource.
/// The resource is freed if necessary.
/// AutoResource takes over ownership of the resource.
explicit AutoResource(FREE_TYPE res = INITIAL_VALUE)
throw(std::bad_exception): _res((RESOURCE_TYPE)res) {
}
/// @brief Takeover ownership from another AutoResource.
AutoResource(AutoResource& o) throw(std::bad_exception):
_res(o.release()) {
}
/// @brief Free resource. Calls @c reset().
~AutoResource() throw(std::bad_exception) {reset();}
/// @brief Assign new resource. Calls @c reset().
/// The resource is freed if necessary.
AutoResource& operator=(RESOURCE_TYPE res) throw(std::bad_exception) {
return reset(res);
}
/// @brief Takeover ownership from another AutoResource.
/// Calls @c reset() from @c this and @c release() from @c other.
AutoResource& operator=(AutoResource& other) throw(std::bad_exception) {
return reset(other.release());
}
/// @brief Get the resource.
operator const RESOURCE_TYPE&() const throw(std::bad_exception) {
return _res;
}
/// @brief find out, if a value is set
/// @return @c true: resource is valid
operator bool() const throw(std::bad_exception) {
return _res!=INITIAL_VALUE;
}
/// @brief get the resetted resource for resetting it.
/// Calls @c reset and returns the cleaned resource.
/// The intention is, that you can safely assign it a new value
/// (e.g. in an expression).
RESOURCE_TYPE& getClean() throw(std::bad_exception) {
reset();
return _res;
}
/// @brief Give away ownership of the resource.
/// @return old resource
RESOURCE_TYPE release() throw(std::bad_exception) {
RESOURCE_TYPE res(_res); _res=INITIAL_VALUE;
return res;
}
/// @brief Assign a new resource.
/// The old resource of @c this is freed if necessary.
AutoResource& reset(RESOURCE_TYPE res = INITIAL_VALUE)
throw(std::bad_exception) {
if (_res!=INITIAL_VALUE) (*FREE_FUNCTION)((FREE_TYPE)_res);
_res = res;
return *this;
}
private:
RESOURCE_TYPE _res; ///< the resource to be managed
};
/** @brief Automatically deletes a pointer when destructed.
@pre #include
mrw::AutoPtr is a replacement for std::auto_ptr. The problem with
standard std::auto_ptr is, that it cannot be stored in a std::map.
@warning Use this class with prudence! Should I ever find out,
how to work around the std::auto_ptr / std::map problem,
then this class may become deprecated.
@param T type of the pointer to manage
*/
template
class AutoPtr {
public:
/// @brief Construct from an allocated resource.
/// The resource is freed if necessary.
/// AutoPtr takes over ownership of the resource.
explicit AutoPtr(T* res = 0)
throw(std::bad_exception): _res(res) {
res = 0;
}
/// @brief Takeover ownership from another AutoPtr.
AutoPtr(AutoPtr& o) throw(std::bad_exception):
_res(o.release()) {
}
/// @brief Free resource. Calls @c reset().
~AutoPtr() throw(std::bad_exception) {reset();}
/// @brief Assign new resource. Calls @c reset().
/// The resource is freed if necessary.
AutoPtr& operator=(T* res) throw(std::bad_exception) {
return reset(res);
}
/// @brief Takeover ownership from another AutoResource.
/// Calls @c reset() from @c this and @c release() from @c other.
AutoPtr& operator=(AutoPtr& other) throw(std::bad_exception) {
return reset(other.release());
}
/// @brief Get the resource.
operator T* const() const throw(std::bad_exception) {
return _res;
}
/// @brief find out, if a value is set
/// @return @c true: resource is valid
operator bool() const throw(std::bad_exception) {
return _res!=0;
}
/// @brief Access the AutoPtr like a normal pointer.
T*const operator->() {return _res;}
/// @brief Dereference the AutoPtr like a normal pointer.
T& operator*() {return *_res;}
/// @brief get the resetted resource for resetting it.
/// Calls @c reset and returns the cleaned resource.
/// The intention is, that you can safely assign it a new value
/// (e.g. in an expression).
T* getClean() throw(std::bad_exception) {
reset();
return _res;
}
/// @brief Give away ownership of the resource.
/// @return old resource
T* release() throw(std::bad_exception) {
T* res(_res); _res=0;
return res;
}
/// @brief Assign a new resource.
/// The old resource of @c this is freed if necessary.
AutoPtr& reset(T* res = 0)
throw(std::bad_exception) {
delete _res;
_res = res;
return *this;
}
private:
T* _res; ///< the resource to be managed
};
/** @brief Automatically closes a file when destructed.
@pre #include
AutoFile works exactly like std::auto_ptr, but for files
instead of pointers. Whenever the context of AutoFile is left,
the opened file is close. This way, resources are freed even in
case of exceptions.
*/
typedef mrw::AutoResource AutoFile;
/** @brief Resource handle for @c mmap.
It integrates pointer and size of a memory mapped file similar
to a @c std::pair.
*/
class MMapHandle {
public:
void* first;
size_t second;
/// @brief Constructor that initializes the values through a call to mmap.
MMapHandle(int, size_t=0, void* = 0,
int = PROT_READ, int = MAP_SHARED, off_t = 0)
throw(std::bad_exception);
/// @brief Reset to zero, value of int is ignored.
MMapHandle& operator=(int) throw(std::bad_exception) {
first = 0; second = 0;
return *this;
}
/// @brief Compare to zero, returns true, if i and handle are both zero.
bool operator==(int i) const throw(std::bad_exception) {
return i==0 && first==0 && second==0;
}
};
inline void munmap(MMapHandle& res) throw(std::bad_exception) {
if (res.first!=0 && res.second>0)
::munmap((char*)res.first, res.second); // char* conversion for windoze cygwin compatibility
}
/** @brief Automatically calls @c munmap on destruction for mmaped files.
@pre #include
It's the same as std::auto_ptr, but for @c mmap instead of @c
new. When the context of @c AutoMapper is left, @c munmap is
called.
*/
typedef mrw::AutoResource
AutoMapper;
/** @brief Automatically calls @c bfd_close for @c bfd*.
@pre #include
It acts like a @c std::auto_ptr, but for @c bfd*, that means it
calls @c bfd_close whenever the context is left.
*/
typedef mrw::AutoResource AutoBfd;
/** @brief Automatically calls @c free for @c malloc allocated memory.
Instanciate it as @c mrw::Auto::Free.
@pre #include
It works like a @c std::auto_ptr, but for memory that was
allocated with @c malloc, not @c new. Memory is freed, whenever
the context od @c AutoFree is left.
@code
{ // enter context
Auto::Free cp = (char*)malloc(5);
cp.getClean() = (char*)malloc(10); // old storage of 5 bytes is freed
} // memory is freed on destruction of cp
@endcode
*/
template class Auto {
public:
typedef mrw::AutoResource Free;
private:
/** @internal
work around compiler warning:
"only defines private constructors and has no friends" */
friend class ThisIsADummyToEliminateWarnings;
/// Forbidden to instanciate.
Auto(); Auto(const Auto&);
};
//@}
}
#endif