Re: C++/CLI is the way to go

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



Philip Daniels wrote:

Sorry this time my post is a bit longer - had to post code too for illustration.

On Sat, 20 Jan 2007 18:05:44 +0100, Andre Kaufmann
<andre.kaufmann_re_move_@xxxxxxxxxxx> wrote:
[...]
Andre

I think that what Jon is saying is that ultimately in the CLR every
reference type "is" a System.Object, hence any solution using a
smartptr ultimately begs the question.

Yes know that.

The CLR has to constantly check
whether an object is a smartptr before it can do "the right thing".

Don't think so.

Arguments:

1) How does the CLR check the objects type when I
add it to a generic list ? They are all objects ?
How can it be typesafe ?

2) I can implement smart pointers in C++/CLI. How is that possible
the C++/CLI code is compiled to IL code ?

3) ! The killer argument ;-9

Delphi implements reference counted objects. InterfacedObjects

AFAIK this Delphi code
compiles directly without a modification
to .NET 1.1 ? How can this be ?

It's not just our code that would be a problem, I am sure there are
many places deep in the .Net runtime where objects are treated in a
generic fashion.

Yes, but why care about it ?

Sample code which illustrates the idea:
(There are many optimizations missing and which are essential for a good smart pointer object !!! - and I haven't tested the code !!!!)
-----------------------------------------------------


##### 1 Embedded counter implementation
########################################

class ReferenceCounter { public long value = 0; }

class SmartPointer<T> : IDisposable where T : class, IDisposable
{
public SmartPointer(T initialPtr)
{
stored = initialPtr;
refcounter.value = 1;
}

public SmartPointer()
{
stored = null;
refcounter.value = 1;
}

public void Assign(SmartPointer<T> r)
{
Discard();
refcounter = r.refcounter;
stored = r.stored;
refcounter.value++;
}

public void Assign(T r)
{
if (stored == r) return;
Discard();
stored = r;
refcounter.value = 1;
}

public void Discard()
{
if (--refcounter.value == 0)
if (stored != null) stored.Dispose();
}

public void Dispose() { Discard(); }
ReferenceCounter refcounter = new ReferenceCounter();
T stored;
};

class SimpleObject : IDisposable
{
public void Dispose() {}
}

static void Main(string[] args)
{
SmartPointer<SimpleObject> p1 =
new SmartPointer<SimpleObject>(new SimpleObject());
SmartPointer<SimpleObject> p2 =
new SmartPointer<SimpleObject>();
p2 = p1;
}



###### 2 Interface based implementation:
########################################

// Base interface for reference counted objects
interface IRefCountedObject
{
ulong AddRef();
ulong Release();
}

// Dumb implementation, only for illustration
// ! not thread safe ..... !!
class BaseRefCounted : IRefCountedObject, IDisposable
{
public ulong AddRef () { return ++l; }
public ulong Release() { if (l == 1) Dispose(); return --l; }
public void Dispose () { }
ulong l = 0;
};


// 2 Objects - first reference counted, second not
class ObjectHasRef : BaseRefCounted { }
class ObjectNoRef { }


// Dumb implementation of a SmartPointer,
// only for illustration, not tested

class SmartPointer<T> : IDisposable where T : class, IRefCountedObject
{
// Assign a new object, this should be also possible with an
// assignment operator !!! for convenience
public void Assign(T r)
{
if (r == stored) return;
if (stored != null) stored.Release();
r.AddRef(); stored = r;
}

// Releases the object and eventually calls Dispose
// if the reference is zero
public void Discard()
{
if (stored != null) stored.Release();
stored = null;
}

public void Dispose() { Discard(); }
T stored; // Points to the reference counted object
};


static void Main(string[] args)
{
ObjectNoRef no = new ObjectNoRef ();
ObjectHasRef yes = new ObjectHasRef();
SmartPointer<IRefCountedObject> p1 = new
SmartPointer<IRefCountedObject>();
SmartPointer<ObjectHasRef> p2 = new
SmartPointer<ObjectHasRef>();

p1.Assign(yes);
p2.Assign(yes);
p1.Assign(no); // Boooom compiler error
}


Please don't sue me for any errors, it was just a quick hack.
So what's missing - some automatism implemented in the CLR, which does the handling, so that I don't have to call an assign method, but can use an assignment operator and would be perfect if the compiler could also generate code which automatically disposes the reference counted object, so optimally the SmartPointer should be a stack allocated / handled object. Like value objects - but smart ;-)

--
Philip Daniels



Andre
.