2004-08-28 16:21:25 +00:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
$Date$
|
|
|
|
$Author$
|
|
|
|
|
|
|
|
@copy © Marc Wäckerlin
|
|
|
|
@license LGPL, see file <a href="license.html">COPYING</a>
|
|
|
|
|
|
|
|
$Log$
|
2004-12-20 07:40:36 +00:00
|
|
|
Revision 1.7 2004/12/20 07:40:35 marc
|
|
|
|
documentation improved, new grouping
|
|
|
|
|
2004-10-11 16:48:29 +00:00
|
|
|
Revision 1.6 2004/10/11 16:48:29 marc
|
|
|
|
better comment and operators -> and * for AutoPtr
|
|
|
|
|
2004-10-11 16:05:02 +00:00
|
|
|
Revision 1.5 2004/10/11 16:05:02 marc
|
|
|
|
new AutoPtr
|
|
|
|
|
2004-10-07 09:24:08 +00:00
|
|
|
Revision 1.4 2004/10/07 09:24:08 marc
|
|
|
|
enhance windoze compatibility
|
|
|
|
|
2004-08-28 16:21:25 +00:00
|
|
|
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<T>
|
|
|
|
- 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
|
|
|
|
|
|
|
|
*/
|
2004-04-21 06:39:20 +00:00
|
|
|
#ifndef __MRW_AUTO_HPP__
|
|
|
|
#define __MRW_AUTO_HPP__
|
|
|
|
|
|
|
|
#include <sys/types.h> // size_t
|
2004-08-28 16:21:25 +00:00
|
|
|
#include <sys/mman.h> // munmap, PROT_READ, MAP_SHARED
|
2004-10-07 09:24:08 +00:00
|
|
|
#include <unistd.h> // close
|
2004-08-28 16:21:25 +00:00
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
// forward
|
|
|
|
class bfd;
|
|
|
|
extern "C" int bfd_close(bfd*);
|
2004-04-21 06:39:20 +00:00
|
|
|
|
|
|
|
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.
|
2004-12-20 07:40:36 +00:00
|
|
|
|
|
|
|
The following ressource handler are predefined:
|
|
|
|
- mrw::AutoPtr<> is the same as std::auto_ptr, but can be stored
|
|
|
|
in STL containers
|
|
|
|
@code
|
|
|
|
mrw::AutoPtr<ClassName> xyz(new ClassName(a, b, c));
|
|
|
|
@endcode
|
|
|
|
- mrw::MMapHandle frees an @c mmap handle with @c munmap
|
|
|
|
- mrw::Auto<>::Free frees @c malloc allocated memory with @c free
|
|
|
|
@code
|
|
|
|
mrw::Auto<char*>::Free xxx((char*)malloc(15));
|
|
|
|
@endcode
|
|
|
|
- mrw::SmartPointer<> is a shared pointer that deletes memory
|
|
|
|
when all owners have died
|
|
|
|
@code
|
|
|
|
mrw::SmartPointer<ClassName> xyz(new ClassName(a, b, c));
|
|
|
|
@endcode
|
|
|
|
- mrw::Pipe handles UNIX pipes and closes them on exit
|
|
|
|
- mrw::AutoFile automatically closes open files
|
|
|
|
- mrw::AutoMapper calls @c munmap on memory mapped files
|
|
|
|
- mrw::AutoBfd automatically calls @c bfd_close
|
|
|
|
|
|
|
|
If this is not enough, you can @c typedef your own ressource
|
|
|
|
handler from the template class mrw::AutoResource<>. For example,
|
|
|
|
mrw::AutoFile is defined as:
|
|
|
|
@code
|
|
|
|
typedef mrw::AutoResource<int, int(*)(int), &close, int, -1> mrw::AutoFile;
|
|
|
|
@endcode
|
2004-04-21 06:39:20 +00:00
|
|
|
*/
|
|
|
|
//@{
|
|
|
|
|
2004-08-28 16:21:25 +00:00
|
|
|
/** @brief Automatically frees a resource when destructed.
|
2004-04-23 16:03:29 +00:00
|
|
|
@pre #include <mrw/auto.hpp>
|
2004-04-21 06:39:20 +00:00
|
|
|
|
2004-08-28 16:21:25 +00:00
|
|
|
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<int, int(*)(int), &close, int, -1> AutoFile;
|
|
|
|
typedef mrw::AutoResource<bfd*, int(*)(bfd*), &bfd_close, int> AutoBfd;
|
|
|
|
template<class T> class Auto {
|
|
|
|
public:
|
|
|
|
typedef mrw::AutoResource<T, void(*)(void*), &free, int, 0> Free;
|
|
|
|
};
|
|
|
|
@endcode
|
2004-10-11 16:48:29 +00:00
|
|
|
@param RESOURCE_TYPE type of the resource to manage
|
2004-08-28 16:21:25 +00:00
|
|
|
@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
|
2004-04-21 06:39:20 +00:00
|
|
|
*/
|
2004-08-28 16:21:25 +00:00
|
|
|
template<typename RESOURCE_TYPE,
|
|
|
|
typename FUNCTION_PTR,
|
|
|
|
FUNCTION_PTR FREE_FUNCTION,
|
|
|
|
typename INITIAL_VALUE_TYPE = RESOURCE_TYPE,
|
|
|
|
INITIAL_VALUE_TYPE INITIAL_VALUE = 0,
|
|
|
|
typename FREE_TYPE = RESOURCE_TYPE>
|
|
|
|
class AutoResource {
|
2004-04-21 06:39:20 +00:00
|
|
|
public:
|
2004-08-28 16:21:25 +00:00
|
|
|
/// @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);
|
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @brief Takeover ownership from another AutoResource.
|
2004-08-28 16:21:25 +00:00
|
|
|
/// Calls @c reset() from @c this and @c release() from @c other.
|
|
|
|
AutoResource& operator=(AutoResource& other) throw(std::bad_exception) {
|
2004-04-21 06:39:20 +00:00
|
|
|
return reset(other.release());
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
/// @brief Get the resource.
|
|
|
|
operator const RESOURCE_TYPE&() const throw(std::bad_exception) {
|
|
|
|
return _res;
|
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @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;
|
|
|
|
}
|
2004-08-28 16:21:25 +00:00
|
|
|
/// @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;
|
2004-04-21 06:39:20 +00:00
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @brief Assign a new resource.
|
2004-08-28 16:21:25 +00:00
|
|
|
/// 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;
|
2004-04-21 06:39:20 +00:00
|
|
|
}
|
|
|
|
private:
|
2004-08-28 16:21:25 +00:00
|
|
|
RESOURCE_TYPE _res; ///< the resource to be managed
|
2004-10-11 16:05:02 +00:00
|
|
|
};
|
|
|
|
|
2004-10-11 16:48:29 +00:00
|
|
|
/** @brief Automatically deletes a pointer when destructed.
|
|
|
|
@pre #include <mrw/auto.hpp>
|
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2004-10-11 16:05:02 +00:00
|
|
|
template <typename T>
|
|
|
|
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);
|
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @brief Takeover ownership from another AutoResource.
|
2004-10-11 16:05:02 +00:00
|
|
|
/// 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;
|
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @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;}
|
2004-10-11 16:05:02 +00:00
|
|
|
/// @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;
|
|
|
|
}
|
2004-10-11 16:48:29 +00:00
|
|
|
/// @brief Assign a new resource.
|
2004-10-11 16:05:02 +00:00
|
|
|
/// 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
|
2004-04-21 06:39:20 +00:00
|
|
|
};
|
|
|
|
|
2004-08-28 16:21:25 +00:00
|
|
|
/** @brief Automatically closes a file when destructed.
|
|
|
|
@pre #include <mrw/auto.hpp>
|
|
|
|
|
|
|
|
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<int, int(*)(int), &close, int, -1> AutoFile;
|
|
|
|
|
2004-10-11 16:48:29 +00:00
|
|
|
/** @brief Resource handle for @c mmap.
|
2004-08-28 16:21:25 +00:00
|
|
|
|
|
|
|
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)
|
2004-10-07 09:24:08 +00:00
|
|
|
::munmap((char*)res.first, res.second); // char* conversion for windoze cygwin compatibility
|
2004-08-28 16:21:25 +00:00
|
|
|
}
|
|
|
|
/** @brief Automatically calls @c munmap on destruction for mmaped files.
|
2004-04-23 16:03:29 +00:00
|
|
|
@pre #include <mrw/auto.hpp>
|
2004-04-21 06:39:20 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2004-08-28 16:21:25 +00:00
|
|
|
typedef mrw::AutoResource<MMapHandle, void(*)(MMapHandle&), &mrw::munmap, int>
|
|
|
|
AutoMapper;
|
2004-04-21 06:39:20 +00:00
|
|
|
|
2004-08-28 16:21:25 +00:00
|
|
|
/** @brief Automatically calls @c bfd_close for @c bfd*.
|
2004-04-23 16:03:29 +00:00
|
|
|
@pre #include <mrw/auto.hpp>
|
2004-04-21 06:39:20 +00:00
|
|
|
|
|
|
|
It acts like a @c std::auto_ptr, but for @c bfd*, that means it
|
|
|
|
calls @c bfd_close whenever the context is left.
|
|
|
|
*/
|
2004-08-28 16:21:25 +00:00
|
|
|
typedef mrw::AutoResource<bfd*, int(*)(bfd*), &bfd_close, int> AutoBfd;
|
2004-04-21 06:39:20 +00:00
|
|
|
|
|
|
|
/** @brief Automatically calls @c free for @c malloc allocated memory.
|
2004-08-28 16:21:25 +00:00
|
|
|
Instanciate it as @c mrw::Auto<TYPE*>::Free.
|
2004-04-23 16:03:29 +00:00
|
|
|
@pre #include <mrw/auto.hpp>
|
2004-04-21 06:39:20 +00:00
|
|
|
|
|
|
|
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.
|
2004-08-28 16:21:25 +00:00
|
|
|
|
|
|
|
@code
|
|
|
|
{ // enter context
|
|
|
|
Auto<char*>::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
|
2004-04-21 06:39:20 +00:00
|
|
|
*/
|
2004-08-28 16:21:25 +00:00
|
|
|
template<class T> class Auto {
|
|
|
|
public:
|
|
|
|
typedef mrw::AutoResource<T, void(*)(void*), &free, int, 0, void*> 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&);
|
2004-04-21 06:39:20 +00:00
|
|
|
};
|
2004-08-28 16:21:25 +00:00
|
|
|
|
2004-04-21 06:39:20 +00:00
|
|
|
//@}
|
|
|
|
}
|
|
|
|
#endif
|