mirror of
https://review.haiku-os.org/haiku
synced 2025-01-18 20:48:48 +01:00
97dc7e3bb2
Otherwise we could cause leaks. Most of the time this check should be optimized out, as most uses of AutoDeleter don't invoke SetTo. But it would have caught some bugs in the VFS refactors (which wound up being cancelled out by later commits anyway, but this would've exposed them.) Just invoke debugger(), which calls the kernel debugger when compiled in kernel mode. And define debugger() inline in this header if OS.h is not included to avoid namespace pollution.
352 lines
6.0 KiB
C++
352 lines
6.0 KiB
C++
/*
|
|
* Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
#ifndef _AUTO_DELETER_H
|
|
#define _AUTO_DELETER_H
|
|
|
|
|
|
/*! Scope-based automatic deletion of objects/arrays.
|
|
ObjectDeleter - deletes an object
|
|
ArrayDeleter - deletes an array
|
|
MemoryDeleter - free()s malloc()ed memory
|
|
CObjectDeleter - calls an arbitrary specified destructor function
|
|
MethodObjectDeleter - calls an arbitrary object function in given struct ptr
|
|
HandleDeleter - use arbitrary handle type and destructor function
|
|
FileDescriptorCloser - closes a file descriptor, based on HandleDeleter
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <SupportDefs.h>
|
|
|
|
#ifndef _OS_H
|
|
extern "C" {
|
|
extern void debugger(const char *message);
|
|
}
|
|
#endif
|
|
|
|
|
|
namespace BPrivate {
|
|
|
|
|
|
// AutoDeleter
|
|
|
|
template<typename C, typename DeleteFunc>
|
|
class AutoDeleter {
|
|
public:
|
|
inline AutoDeleter()
|
|
: fObject(NULL)
|
|
{
|
|
}
|
|
|
|
inline AutoDeleter(C *object)
|
|
: fObject(object)
|
|
{
|
|
}
|
|
|
|
inline ~AutoDeleter()
|
|
{
|
|
DeleteFunc destructor;
|
|
destructor(fObject);
|
|
}
|
|
|
|
inline void SetTo(C *object)
|
|
{
|
|
if (object == fObject && object != NULL)
|
|
debugger("identical objects");
|
|
|
|
if (object != fObject) {
|
|
DeleteFunc destructor;
|
|
destructor(fObject);
|
|
fObject = object;
|
|
}
|
|
}
|
|
|
|
inline void Unset()
|
|
{
|
|
SetTo(NULL);
|
|
}
|
|
|
|
inline void Delete()
|
|
{
|
|
SetTo(NULL);
|
|
}
|
|
|
|
inline bool IsSet() const
|
|
{
|
|
return fObject != NULL;
|
|
}
|
|
|
|
inline C *Get() const
|
|
{
|
|
return fObject;
|
|
}
|
|
|
|
inline C *Detach()
|
|
{
|
|
C *object = fObject;
|
|
fObject = NULL;
|
|
return object;
|
|
}
|
|
|
|
inline C *operator->() const
|
|
{
|
|
return fObject;
|
|
}
|
|
|
|
protected:
|
|
C *fObject;
|
|
|
|
private:
|
|
AutoDeleter(const AutoDeleter&);
|
|
AutoDeleter& operator=(const AutoDeleter&);
|
|
};
|
|
|
|
|
|
// ObjectDeleter
|
|
|
|
template<typename C>
|
|
struct ObjectDelete
|
|
{
|
|
inline void operator()(C *object)
|
|
{
|
|
delete object;
|
|
}
|
|
};
|
|
|
|
template<typename C>
|
|
struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
|
|
{
|
|
ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
|
|
ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
|
|
};
|
|
|
|
|
|
// ArrayDeleter
|
|
|
|
template<typename C>
|
|
struct ArrayDelete
|
|
{
|
|
inline void operator()(C *array)
|
|
{
|
|
delete[] array;
|
|
}
|
|
};
|
|
|
|
template<typename C>
|
|
struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
|
|
{
|
|
ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
|
|
ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}
|
|
|
|
inline C& operator[](size_t index) const
|
|
{
|
|
return this->Get()[index];
|
|
}
|
|
};
|
|
|
|
|
|
// MemoryDeleter
|
|
|
|
struct MemoryDelete
|
|
{
|
|
inline void operator()(void *memory)
|
|
{
|
|
free(memory);
|
|
}
|
|
};
|
|
|
|
struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
|
|
{
|
|
MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
|
|
MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
|
|
};
|
|
|
|
|
|
// CObjectDeleter
|
|
|
|
template<typename Type, typename DestructorReturnType,
|
|
DestructorReturnType (*Destructor)(Type*)>
|
|
struct CObjectDelete
|
|
{
|
|
inline void operator()(Type *object)
|
|
{
|
|
if (object != NULL)
|
|
Destructor(object);
|
|
}
|
|
};
|
|
|
|
template<typename Type, typename DestructorReturnType,
|
|
DestructorReturnType (*Destructor)(Type*)>
|
|
struct CObjectDeleter
|
|
: AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> >
|
|
{
|
|
typedef AutoDeleter<Type,
|
|
CObjectDelete<Type, DestructorReturnType, Destructor> > Base;
|
|
|
|
CObjectDeleter() : Base()
|
|
{
|
|
}
|
|
|
|
CObjectDeleter(Type *object) : Base(object)
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
// MethodDeleter
|
|
|
|
template<typename Type, typename DestructorReturnType,
|
|
DestructorReturnType (Type::*Destructor)()>
|
|
struct MethodDelete
|
|
{
|
|
inline void operator()(Type *object)
|
|
{
|
|
if (object != NULL)
|
|
(object->*Destructor)();
|
|
}
|
|
};
|
|
|
|
|
|
template<typename Type, typename DestructorReturnType,
|
|
DestructorReturnType (Type::*Destructor)()>
|
|
struct MethodDeleter
|
|
: AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> >
|
|
{
|
|
typedef AutoDeleter<Type,
|
|
MethodDelete<Type, DestructorReturnType, Destructor> > Base;
|
|
|
|
MethodDeleter() : Base()
|
|
{
|
|
}
|
|
|
|
MethodDeleter(Type *object) : Base(object)
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
// MethodObjectDeleter
|
|
|
|
template<typename Type, typename Table, Table **table,
|
|
void (*Table::*Deleter)(Type*)>
|
|
struct MethodObjectDelete {
|
|
inline void operator()(Type *object)
|
|
{
|
|
if (object != NULL)
|
|
((**table).*Deleter)(object);
|
|
}
|
|
};
|
|
|
|
template<typename Type, typename Table, Table **table,
|
|
typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)>
|
|
struct MethodObjectDeleter
|
|
: AutoDeleter<Type, MethodObjectDelete<Type, Table, table, Deleter> >
|
|
{
|
|
typedef AutoDeleter<Type,
|
|
MethodObjectDelete<Type, Table, table, Deleter> > Base;
|
|
|
|
MethodObjectDeleter() : Base() {}
|
|
MethodObjectDeleter(Type *object) : Base(object) {}
|
|
};
|
|
|
|
|
|
// HandleDeleter
|
|
|
|
struct StatusHandleChecker
|
|
{
|
|
inline bool operator()(status_t handle)
|
|
{
|
|
return handle >= B_OK;
|
|
}
|
|
};
|
|
|
|
template<typename C, typename DestructorResult,
|
|
DestructorResult (*Destructor)(C), C nullValue = -1,
|
|
typename Checker = StatusHandleChecker>
|
|
class HandleDeleter {
|
|
public:
|
|
inline HandleDeleter()
|
|
: fHandle(nullValue)
|
|
{
|
|
}
|
|
|
|
inline HandleDeleter(C handle)
|
|
: fHandle(handle)
|
|
{
|
|
}
|
|
|
|
inline ~HandleDeleter()
|
|
{
|
|
if (IsSet())
|
|
Destructor(fHandle);
|
|
}
|
|
|
|
inline void SetTo(C handle)
|
|
{
|
|
if (handle != fHandle) {
|
|
if (IsSet())
|
|
Destructor(fHandle);
|
|
fHandle = handle;
|
|
}
|
|
}
|
|
|
|
inline void Unset()
|
|
{
|
|
SetTo(nullValue);
|
|
}
|
|
|
|
inline void Delete()
|
|
{
|
|
SetTo(nullValue);
|
|
}
|
|
|
|
inline bool IsSet() const
|
|
{
|
|
Checker isHandleSet;
|
|
return isHandleSet(fHandle);
|
|
}
|
|
|
|
inline C Get() const
|
|
{
|
|
return fHandle;
|
|
}
|
|
|
|
inline C Detach()
|
|
{
|
|
C handle = fHandle;
|
|
fHandle = nullValue;
|
|
return handle;
|
|
}
|
|
|
|
protected:
|
|
C fHandle;
|
|
|
|
private:
|
|
HandleDeleter(const HandleDeleter&);
|
|
HandleDeleter& operator=(const HandleDeleter&);
|
|
};
|
|
|
|
|
|
// FileDescriptorCloser
|
|
|
|
typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser;
|
|
|
|
|
|
} // namespace BPrivate
|
|
|
|
|
|
using ::BPrivate::ObjectDeleter;
|
|
using ::BPrivate::ArrayDeleter;
|
|
using ::BPrivate::MemoryDeleter;
|
|
using ::BPrivate::CObjectDeleter;
|
|
using ::BPrivate::MethodDeleter;
|
|
using ::BPrivate::MethodObjectDeleter;
|
|
using ::BPrivate::HandleDeleter;
|
|
using ::BPrivate::FileDescriptorCloser;
|
|
|
|
|
|
#endif // _AUTO_DELETER_H
|