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.
 
 
 
 
 
 

162 lines
4.1 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
INFSCAN
blob.h
Abstract:
Conceptual blob of data (smart pointer variation)
this allows passing of a large object around
like a pointer but with cleanup if stack is unwound (eg, due to an exception)
and can also be passed into the STL constructs
blob<basetype> creates a container object. One container object
can create the blob.
ASSUMPTIONS:
blob<x> val1,val2;
thread1 & thread2 calling "val1.create()" is *not* thread safe
thread1 & thread2 calling "val1=val2" is *not* thread safe
thread1 calling "val1=val2" where val2 owned by thread 2 *is* thread safe
as long as no other threads are trying to assign a value to val1.
ie assignment of an instance of blob<x> is *not* thread safe, however
the referenced 'pointer' of blob<x> *is* thread safe
This requires interlocked ref-counting on the shared data
History:
Created July 2001 - JamieHun
--*/
#ifndef _INFSCAN_BLOB_H_
#define _INFSCAN_BLOB_H_
template <class _Ty> class blob {
private:
typedef blob<_Ty> _Myt;
typedef _Ty value_type;
class _Item {
//
// the allocated structure
//
public:
LONG _Reference;
value_type _Object;
_Item() {
_Reference = 1;
}
void _AddRef() {
if(this) {
//
// needs to be thread-safe as two different threads
// can access the same _Item
// to inc/dec
//
InterlockedIncrement(&_Reference);
}
}
void _Release() {
if(this) {
//
// needs to be thread-safe as two different threads
// can access the same _Item
// to inc/dec
//
// obviously if one is dec'ing to zero, nobody else
// has a reference to it
//
if(InterlockedDecrement(&_Reference) == 0) {
delete this;
}
}
}
};
//
// pointer to this special structure
//
_Item *_pItem;
public:
_Myt & create(void) {
_pItem->_Release();
_pItem = NULL;
_pItem = new _Item; // might throw
return *this;
}
blob(bool f = false) {
_pItem = NULL;
if(f) {
create();
}
}
//
// const implies constness of data
// AddRef doesn't effect true constness of data
// it's a behind the scenes thing
//
blob(const _Myt & other) {
const_cast<_Item*>(other._pItem)->_AddRef();
_pItem = other._pItem;
}
_Myt & operator=(const _Myt & other) {
if(_pItem != other._pItem) {
const_cast<_Item*>(other._pItem)->_AddRef();
_pItem->_Release();
_pItem = other._pItem;
}
return *this;
}
bool operator==(const _Myt & other) const {
return _pItem == other._pItem;
}
bool operator!=(const _Myt & other) const {
return _pItem == other._pItem;
}
operator bool() const {
return _pItem ? true : false;
}
bool operator!() const {
return _pItem ? false : true;
}
operator value_type*() const {
if(_pItem) {
return &_pItem->_Object;
} else {
return NULL;
}
}
operator value_type&() const {
if(_pItem) {
return _pItem->_Object;
} else {
throw bad_pointer();
}
}
value_type& operator*() const {
if(_pItem) {
return _pItem->_Object;
} else {
throw bad_pointer();
}
}
value_type* operator->() const {
if(_pItem) {
return &_pItem->_Object;
} else {
return NULL;
}
}
};
#endif // !_INFSCAN_BLOB_H_