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:
parent
baf05fd515
commit
55e0ea52bd
4 changed files with 339 additions and 0 deletions
15
SWIG/Examples/test-suite/python/refcount_runme.py
Normal file
15
SWIG/Examples/test-suite/python/refcount_runme.py
Normal 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"
|
||||||
|
|
||||||
|
|
||||||
198
SWIG/Examples/test-suite/refcount.h
Normal file
198
SWIG/Examples/test-suite/refcount.h
Normal 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__
|
||||||
116
SWIG/Examples/test-suite/refcount.i
Normal file
116
SWIG/Examples/test-suite/refcount.i
Normal 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(); }
|
||||||
|
|
||||||
|
*/
|
||||||
10
SWIG/Examples/test-suite/ruby/refcount_runme.rb
Normal file
10
SWIG/Examples/test-suite/ruby/refcount_runme.rb
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue