added refcount example using the old macro way and the proposed ref/unref features

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5667 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-01-22 06:26:17 +00:00
commit 55e0ea52bd
4 changed files with 339 additions and 0 deletions

View file

@ -0,0 +1,15 @@
from refcount import *
#
# very innocent example
#
a = A3()
b1 = B(a)
b2 = B.create(a)
if a.ref_count() != 3:
print "This program will crash... now"

View file

@ -0,0 +1,198 @@
#ifndef __test_suite_refcount_h__
#define __test_suite_refcount_h__
struct RCObjBase {
/*!
Return the numbers of active references.
\return The internal \c refCount value.
*/
int ref_count() const
{
return refCount;
}
/*!
Add one reference.
\return The reference counter value.
*/
int ref() const
{
return add_ref();
}
/*!
Delete one reference. If the refCount is zero, the
object is deleted.
\return The reference counter value, which can be zero after
deletion.
*/
int unref() const
{
if (ref_count() == 0 || del_ref() == 0 )
{
delete this;
return 0;
}
return ref_count();
}
protected:
RCObjBase();
RCObjBase(const RCObjBase& );
virtual ~RCObjBase() = 0;
private:
RCObjBase& operator=(const RCObjBase& );
friend class RCObj;
int add_ref() const
{
return ++refCount;
}
int del_ref() const
{
return --refCount;
}
mutable int refCount;
};
struct RCObj : virtual RCObjBase {
protected:
RCObj()
{
}
};
/*! Reference an RCObj object
\return The input pointer \a r
*/
template <class T>
inline
T* ref(T* r)
{
return (r && r->ref() ) ? r : 0;
}
/*! Unreference an RCObj object.
\return The input pointer \a r or nil if the object was deleted.
*/
template <class T>
inline
T* unref(T* r)
{
return ( r && r->unref() ) ? r : 0;
}
RCObjBase::RCObjBase()
: refCount(0)
{
}
RCObjBase::~RCObjBase()
{
}
RCObjBase::RCObjBase(const RCObjBase&)
: refCount(0)
{
}
RCObjBase& RCObjBase::operator=(const RCObjBase&)
{
return *this;
}
template <class T>
struct RCPtr {
typedef T* pointer_type;
typedef T& refernce_type;
typedef T value_type;
RCPtr();
RCPtr(T* realPtr);
RCPtr(const RCPtr& rhs);
~RCPtr();
RCPtr& operator=(const RCPtr& rhs);
RCPtr& operator=(T* realPtr);
T* operator->() { return pointee; }
T& operator*() { return *pointee; }
const T* operator->() const { return pointee; }
const T& operator*() const { return *pointee; }
operator T*() { return pointee; }
operator T&() { return *pointee; }
operator const T*() const { return pointee; }
operator const T&() const { return *pointee; }
T* get() { return pointee; }
T* get() const { return pointee; }
private:
T* pointee;
};
template <class T>
inline
RCPtr<T>::RCPtr()
: pointee(0)
{
}
template <class T>
inline
RCPtr<T>::RCPtr(T* realPtr)
: pointee(realPtr)
{
ref(pointee);
}
template <class T>
inline
RCPtr<T>::RCPtr(const RCPtr& rhs)
: pointee(rhs.pointee)
{
ref(pointee);
}
template <class T>
inline
RCPtr<T>::~RCPtr()
{
unref(pointee);
}
template <class T>
inline
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs)
{
if (pointee != rhs.pointee) {
unref(pointee);
pointee = rhs.pointee;
ref(pointee);
}
return *this;
}
#endif //__test_suite_refcount_h__

View file

@ -0,0 +1,116 @@
%module refcount
#pragma SWIG nowarn=362
%{
#include <iostream>
#include "refcount.h"
%}
#if 1
//
// the old macro way
//
%define RefCount(...)
%typemap(newfree) __VA_ARGS__* { $1->ref(); }
%newobject __VA_ARGS__::clone();
%extend __VA_ARGS__ { ~__VA_ARGS__() { self->unref(); } }
%ignore __VA_ARGS__::~__VA_ARGS__();
%enddef
//
// you need to apply the RefCount macro to all the RCObj derived
// classes.
//
RefCount(RCObj);
RefCount(A);
RefCount(A1);
RefCount(A2);
RefCount(A3);
RefCount(B);
#else
//
// using the ref/unref features you can active the ref. counting
// for RCObj and all its descendents at once
//
%feature("refbase") RCObj "$this->ref();"
%feature("unrefbase") RCObj "$this->unref();"
#endif
%include "refcount.h"
%newobject B::create();
%newobject B::cloner();
%inline %{
struct A : RCObj
{
A() {}
~A()
{
// std::cout << "deleting a" << std::endl;
}
#ifdef SWIGRUBY
// fix strange ruby + virtual derivation problem
using RCObjBase::ref_count;
#endif
};
struct A1 : A
{
protected:
A1() {}
};
struct A2 : A
{
};
struct A3 : A1, private A2
{
};
struct B : RCObj
{
B(A* a) : _a(a) {}
static B* create(A* a)
{
return new B(a);
}
B* cloner()
{
return new B(_a);
}
~B()
{
// std::cout << "deleting b" << std::endl;
}
private:
RCPtr<A> _a;
};
%}
/* Other ref/unref uses:
// deactive the refcounting for A1
%feature("noref") A1;
%feature("nounref") A1;
// deactive the refcounting for A2 and all its descendents
%feature("norefbase") A2;
%feature("nounrefbase") A2;
// active the refcounting only for A3
%feature("ref") A3 { $this->ref(); }
%feature("unref") A3 { $this->unref(); }
*/

View file

@ -0,0 +1,10 @@
require 'refcount'
a = Refcount::A3.new;
b1 = Refcount::B.new a;
b2 = Refcount::B.new a;
if a.ref_count() != 3
print "This program will crash... now\n"
end