Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

450 lines
9.4 KiB

/*
* E X \ A U T O P T R . H
*
* Implementation of automatic-cleanup pointer template classes.
* This implementation is safe for use in NON-throwing environments
* (save for EXDAV & other store-loaded components).
*
* Copyright 1986-1998 Microsoft Corporation, All Rights Reserved.
*/
//----------------------------------------------------------------------//
//
// Automatic pointers defined here:
//
// auto_ptr<>
// auto_heap_ptr<>
// auto_handle<>
// auto_heap_array<>
// auto_ref_ptr<CRefCountedObject>
//
#ifndef _EX_AUTOPTR_H_
#define _EX_AUTOPTR_H_
#include <caldbg.h>
#include <calrc.h>
#include <ex\exmem.h>
#pragma warning(disable: 4284) // operator-> to a non UDT
// ========================================================================
//
// TEMPLATE CLASS auto_ptr
//
// Stripped down auto_ptr class based on the C++ STL standard one
//
// Calls delete on dtor.
// NO equals operator between these classes, as that hides
// the transfer-of-ownership. Handle those yourself, EXPLICITLY,
// like this:
// auto-ptr1 = auto-ptr2.relinquish();
//
template<class X>
class auto_ptr
{
protected:
X * px;
// NOT IMPLEMENTED
//
auto_ptr(const auto_ptr<X>& p);
auto_ptr& operator=(const auto_ptr<X>& p);
public:
// CONSTRUCTORS
//
explicit auto_ptr(X* p=0) : px(p) {}
~auto_ptr()
{
delete px;
}
// ACCESSORS
//
bool operator!()const { return (px == NULL); }
operator X*() const { return px; }
// X& operator*() const { Assert (px); return *px; }
X* operator->() const { Assert (px); return px; }
X* get() const { return px; }
// MANIPULATORS
//
X* relinquish() { X* p = px; px = 0; return p; }
X** operator&() { Assert (!px); return &px; }
void clear()
{
delete px;
px = NULL;
}
auto_ptr& operator=(X* p)
{
Assert(!px); // Scream on overwrite of good data.
px = p;
return *this;
}
};
// ========================================================================
//
// TEMPLATE CLASS auto_handle
//
// auto_ptr for NT system handles.
//
// Closes the handle on dtor.
// NO equals operator between these classes, as that hides
// the transfer-of-ownership. Handle those yourself, EXPLICITLY,
// like this:
// auto-handle-1 = auto-handle-2.relinquish();
//
template<class X>
class auto_handle
{
private:
X handle;
// NOT IMPLEMENTED
//
auto_handle(const auto_handle<X>& h);
auto_handle& operator=(auto_handle<X>& h);
public:
// CONSTRUCTORS
//
auto_handle(X h=0) : handle(h) {}
~auto_handle()
{
if (handle && INVALID_HANDLE_VALUE != handle)
{
CloseHandle(handle);
}
}
// ACCESSORS
//
operator X() const { return handle; }
X get() const { return handle; }
// MANIPULATORS
//
X relinquish() { X h = handle; handle = 0; return h; }
X* load() { Assert(NULL==handle); return &handle; }
X* operator&() { Assert(NULL==handle); return &handle; }
void clear()
{
if (handle && INVALID_HANDLE_VALUE != handle)
{
CloseHandle(handle);
}
handle = 0;
}
auto_handle& operator=(X h)
{
Assert (handle == 0); // Scream on overwrite of good data
handle = h;
return *this;
}
};
// ========================================================================
//
// TEMPLATE CLASS auto_ref_ptr
//
// Holds a ref on an object. Works with CRefCountedObject.
// Grabs a ref when a pointer is assigned into this object.
// Releases the ref when this object is destroyed.
//
template<class X>
class auto_ref_ptr
{
private:
X * m_px;
void init()
{
if ( m_px )
{
m_px->AddRef();
}
}
void deinit()
{
if ( m_px )
{
m_px->Release();
}
}
// NOT IMPLEMENTED
// We turn off operator new to try to prevent auto_ref_ptrs being
// created via new(). However, storext.h uses a macro to redefine new,
// so this line is only used on non-DBG.
#ifndef DBG
void * operator new(size_t cb);
#endif // !DBG
public:
// CONSTRUCTORS
//
explicit auto_ref_ptr(X* px=0) :
m_px(px)
{
init();
}
auto_ref_ptr(const auto_ref_ptr<X>& rhs) :
m_px(rhs.m_px)
{
init();
}
~auto_ref_ptr()
{
deinit();
}
// ACCESSORS
//
X& operator*() const { return *m_px; }
X* operator->() const { return m_px; }
X* get() const { return m_px; }
// MANIPULATORS
//
X* relinquish() { X* p = m_px; m_px = 0; return p; }
X** load() { Assert(NULL==m_px); return &m_px; }
X* take_ownership(X* p) { Assert(NULL==m_px); return m_px = p; }
void clear()
{
deinit();
m_px = NULL;
}
auto_ref_ptr& operator=(const auto_ref_ptr<X>& rhs)
{
if ( m_px != rhs.m_px )
{
deinit();
m_px = rhs.m_px;
init();
}
return *this;
}
auto_ref_ptr& operator=(X* px)
{
if ( m_px != px )
{
deinit();
m_px = px;
init();
}
return *this;
}
};
// ========================================================================
//
// TEMPLATE CLASS auto_heap_ptr
//
// An auto_ptr class based on the heap instead of new.
//
// Calls ExFree() on dtor.
// NO equals operator between these classes, as that hides
// the transfer-of-ownership. Handle those yourself, EXPLICITLY,
// like this:
// auto-heap-ptr1 = auto-heap-ptr2.relinquish();
//
template<class X>
class auto_heap_ptr
{
private:
X * m_px;
// NOT IMPLEMENTED
//
auto_heap_ptr (const auto_heap_ptr<X>& p);
auto_heap_ptr& operator= (const auto_heap_ptr<X>& p);
//void * operator new(size_t cb);
public:
// CONSTRUCTORS
//
explicit auto_heap_ptr (X* p=0) : m_px(p) {}
~auto_heap_ptr()
{
clear();
}
// ACCESSORS
//
// NOTE: this simple cast operator (operator X*()) allows
// the [] operator to function.
//$REVIEW: Should we add an explicit [] operator?
operator X*() const { return m_px; }
X* operator->() const { Assert (m_px); return m_px; }
X* get() const { return m_px; }
//X& operator[] (UINT index) const { return *(m_px + index); }
//X& operator[] (UINT index) const { return m_px[index]; }
// MANIPULATORS
//
X* relinquish() { X* p = m_px; m_px = 0; return p; }
X** load() { Assert(!m_px); return &m_px; }
//$REVIEW: Can we migrate all users of operator&() to use load() instead???
//$REVIEW: Benefit: it's more explicit. Detriment: need to change existing code.
X** operator&() { Assert (!m_px); return &m_px; }
void clear()
{
if (m_px) // Release any object we're holding now
{
ExFree (m_px);
}
m_px = NULL;
}
// Realloc
//$REVIEW:
// This operator is technically NOT safe for store-side code!
// It makes it easy to ignore memory failures.
// (However, it is currently so ingrained in our vocabulary that
// removing it will touch a very large number of files: )
// For now, to be safe, callers MUST check the value of their
// object (using .get()) after calling this function.
//
void realloc(UINT cb)
{
VOID * pvTemp;
if (m_px)
pvTemp = ExRealloc (m_px, cb);
else
pvTemp = ExAlloc (cb);
Assert (pvTemp);
m_px = reinterpret_cast<X*>(pvTemp);
}
//$REVIEW: end
// Failing Realloc
//
BOOL frealloc(UINT cb)
{
VOID * pvTemp;
if (m_px)
pvTemp = ExRealloc (m_px, cb);
else
pvTemp = ExAlloc (cb);
if (!pvTemp)
return FALSE;
m_px = static_cast<X*>(pvTemp);
return TRUE;
}
// NOTE: This method asserts if the auto-pointer already holds a value.
// Use clear() or relinquish() to clear the old value before
// taking ownership of another value.
//
void take_ownership (X * p)
{
Assert (!m_px); // Scream on overwrite of good data.
m_px = p;
}
// NOTE: This operator= is meant to do exactly the same as take_ownership().
//
auto_heap_ptr& operator= (X * p)
{
Assert (!m_px); // Scream on overwrite of good data.
m_px = p;
return *this;
}
};
// ========================================================================
//
// TEMPLATE CLASS auto_co_task_mem
//
// Stripped down auto_co_task_mem class based on the C++ STL standard one
//
// Calls CoTaskMemFree on dtor.
// NO equals operator between these classes, as that hides
// the transfer-of-ownership. Handle those yourself, EXPLICITLY,
// like this:
// auto-co_task_mem1 = auto-co_task_mem2.relinquish();
//
template<class X>
class auto_co_task_mem
{
protected:
X * m_px;
// NOT IMPLEMENTED
//
auto_co_task_mem(const auto_co_task_mem<X>& p);
auto_co_task_mem& operator=(const auto_co_task_mem<X>& p);
public:
// CONSTRUCTORS
//
explicit auto_co_task_mem(X* p=0) : m_px(p) {}
~auto_co_task_mem()
{
CoTaskMemFree(m_px);
}
// ACCESSORS
//
X* operator->() const { Assert (m_px); return m_px; }
X* get() const { return m_px; }
// MANIPULATORS
//
X* relinquish() { X* p = m_px; m_px = 0; return p; }
X** load() { Assert(!m_px); return &m_px; }
X** operator&() { Assert (!m_px); return &m_px; }
void clear()
{
CoTaskMemFree(m_px);
m_px = NULL;
}
// NOTE: This method asserts if the auto-pointer already holds a value.
// Use clear() or relinquish() to clear the old value before
// taking ownership of another value.
//
void take_ownership (X * p)
{
Assert (!m_px); // Scream on overwrite of good data.
m_px = p;
}
auto_co_task_mem& operator=(X* p)
{
Assert(!m_px); // Scream on overwrite of good data.
m_px = p;
return *this;
}
};
#endif //!_EX_AUTOPTR_H_