forked from amazingfate/loongoffice
by converting the bit munging to use bitfields. Remove unused return values. Add asserts to check that AddRef() is not called after the object is deleted. Fix the code in SfxObjectShell to not call AddRef() after SfxObjectShell is deleted. Change-Id: I3a3565a0bc45fc9d1d086222265ab8b8175818a7
255 lines
6.8 KiB
C++
255 lines
6.8 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#ifndef INCLUDED_TOOLS_REF_HXX
|
|
#define INCLUDED_TOOLS_REF_HXX
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include <tools/toolsdllapi.h>
|
|
#include <vector>
|
|
|
|
namespace tools {
|
|
|
|
/** T must be a class that extends SvRefBase */
|
|
template<typename T> class SvRef {
|
|
public:
|
|
SvRef(): pObj(0) {}
|
|
|
|
SvRef(SvRef const & rObj): pObj(rObj.pObj)
|
|
{
|
|
if (pObj != 0) pObj->AddNextRef();
|
|
}
|
|
|
|
SvRef(T * pObjP): pObj(pObjP)
|
|
{
|
|
if (pObj != 0) pObj->AddRef();
|
|
}
|
|
|
|
~SvRef()
|
|
{
|
|
if (pObj != 0) pObj->ReleaseRef();
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
if (pObj != 0) {
|
|
T * pRefObj = pObj;
|
|
pObj = 0;
|
|
pRefObj->ReleaseRef();
|
|
}
|
|
}
|
|
|
|
SvRef & operator =(SvRef const & rObj)
|
|
{
|
|
if (rObj.pObj != 0) {
|
|
rObj.pObj->AddNextRef();
|
|
}
|
|
T * pRefObj = pObj;
|
|
pObj = rObj.pObj;
|
|
if (pRefObj != 0) {
|
|
pRefObj->ReleaseRef();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool Is() const { return pObj != 0; }
|
|
|
|
T * operator &() const { return pObj; }
|
|
|
|
T * operator ->() const { assert(pObj != 0); return pObj; }
|
|
|
|
T & operator *() const { assert(pObj != 0); return *pObj; }
|
|
|
|
operator T *() const { return pObj; }
|
|
|
|
protected:
|
|
T * pObj;
|
|
};
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
class SvRefMemberList : private std::vector<T>
|
|
{
|
|
private:
|
|
typedef typename std::vector<T> base_t;
|
|
|
|
public:
|
|
using base_t::size;
|
|
using base_t::front;
|
|
using base_t::back;
|
|
using base_t::operator[];
|
|
using base_t::begin;
|
|
using base_t::end;
|
|
using typename base_t::iterator;
|
|
using typename base_t::const_iterator;
|
|
using base_t::rbegin;
|
|
using base_t::rend;
|
|
using typename base_t::reverse_iterator;
|
|
using base_t::empty;
|
|
|
|
inline ~SvRefMemberList() { clear(); }
|
|
inline void clear()
|
|
{
|
|
for( typename base_t::const_iterator it = base_t::begin(); it != base_t::end(); ++it )
|
|
{
|
|
T p = *it;
|
|
if( p )
|
|
p->ReleaseRef();
|
|
}
|
|
base_t::clear();
|
|
}
|
|
|
|
inline void push_back( T p )
|
|
{
|
|
base_t::push_back( p );
|
|
p->AddRef();
|
|
}
|
|
|
|
inline void insert(const SvRefMemberList& rOther)
|
|
{
|
|
for( typename base_t::const_iterator it = rOther.begin(); it != rOther.end(); ++it )
|
|
{
|
|
push_back(*it);
|
|
}
|
|
}
|
|
|
|
inline T pop_back()
|
|
{
|
|
T p = base_t::back();
|
|
base_t::pop_back();
|
|
if( p )
|
|
p->ReleaseRef();
|
|
return p;
|
|
}
|
|
};
|
|
|
|
|
|
/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */
|
|
class TOOLS_DLLPUBLIC SvRefBase
|
|
{
|
|
// the only reason this is not bool is because MSVC cannot handle mixed type bitfields
|
|
unsigned int bNoDelete : 1;
|
|
unsigned int nRefCount : 31;
|
|
|
|
protected:
|
|
virtual ~SvRefBase();
|
|
virtual void QueryDelete();
|
|
|
|
public:
|
|
SvRefBase() : bNoDelete(1), nRefCount(0) {}
|
|
|
|
SvRefBase( const SvRefBase & /* rObj */ ) : bNoDelete(1), nRefCount(0) {}
|
|
|
|
SvRefBase & operator = ( const SvRefBase & )
|
|
{ return *this; }
|
|
|
|
void RestoreNoDelete()
|
|
{ bNoDelete = 1; }
|
|
|
|
void AddNextRef()
|
|
{
|
|
assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
|
|
++nRefCount;
|
|
}
|
|
|
|
void AddRef()
|
|
{
|
|
assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
|
|
if( bNoDelete )
|
|
bNoDelete = 0;
|
|
++nRefCount;
|
|
}
|
|
|
|
void ReleaseRef()
|
|
{
|
|
assert( nRefCount >= 1);
|
|
if( --nRefCount == 0 && !bNoDelete)
|
|
QueryDelete();
|
|
}
|
|
|
|
unsigned int GetRefCount() const
|
|
{ return nRefCount; }
|
|
};
|
|
|
|
template<typename T>
|
|
class SvCompatWeakBase;
|
|
|
|
/** SvCompatWeakHdl acts as a intermediary between SvCompatWeakRef<T> and T.
|
|
*/
|
|
template<typename T>
|
|
class SvCompatWeakHdl : public SvRefBase
|
|
{
|
|
friend class SvCompatWeakBase<T>;
|
|
T* _pObj;
|
|
|
|
SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
|
|
|
|
public:
|
|
void ResetWeakBase( ) { _pObj = 0; }
|
|
T* GetObj() { return _pObj; }
|
|
};
|
|
|
|
/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame.
|
|
Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted.
|
|
*/
|
|
template<typename T>
|
|
class SvCompatWeakBase
|
|
{
|
|
tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
|
|
|
|
public:
|
|
/** Does not use initializer due to compiler warnings,
|
|
because the lifetime of the _xHdl object can exceed the lifetime of this class.
|
|
*/
|
|
SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); }
|
|
|
|
~SvCompatWeakBase() { _xHdl->ResetWeakBase(); }
|
|
|
|
SvCompatWeakHdl<T>* GetHdl() { return _xHdl; }
|
|
};
|
|
|
|
/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak.
|
|
*/
|
|
template<typename T>
|
|
class SvCompatWeakRef
|
|
{
|
|
tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
|
|
public:
|
|
inline SvCompatWeakRef( ) {}
|
|
inline SvCompatWeakRef( T* pObj )
|
|
{ if( pObj ) _xHdl = pObj->GetHdl(); }
|
|
inline SvCompatWeakRef& operator = ( T * pObj )
|
|
{ _xHdl = pObj ? pObj->GetHdl() : 0; return *this; }
|
|
inline bool Is() const
|
|
{ return _xHdl.Is() && _xHdl->GetObj(); }
|
|
inline T* operator -> () const
|
|
{ return _xHdl.Is() ? _xHdl->GetObj() : 0; }
|
|
inline T* operator & () const
|
|
{ return _xHdl.Is() ? _xHdl->GetObj() : 0; }
|
|
inline operator T* () const
|
|
{ return _xHdl.Is() ? _xHdl->GetObj() : 0; }
|
|
};
|
|
|
|
#endif
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|