Gabriel,
I slept on you question and this is what I came up with. Bascially it creates intermidiary layer that does the reference counting. Kinda fun little coding over morning coffee. I tried to comment it enough to make sense.
Maybe it will help, good luck
Doug Stastny
I slept on you question and this is what I came up with. Bascially it creates intermidiary layer that does the reference counting. Kinda fun little coding over morning coffee. I tried to comment it enough to make sense.
SuperStrict Rem TExternal is only to simulate an externally managed object that can be returned multiple times per function call. We are just going to store objects in simple stringlist, nothing fancy or fast Our handle is nothing more than memory address of the first element of data in the object. it will be consistent for all instances pointing to this object. End Rem Type TExternal Field _Text:String Method Handle:Int() Return Int(Byte Ptr(Self)) End Method End Type Global ExternalObjects : TList=New TList Rem A function that gets external handle for string in string list function will return handle to same item if already exists End Rem Function GetExternal:Int(Text:String) For Local e:TExternal=EachIn ExternalObjects If e._Text=Text Print "Reusing "+Text Return e.Handle() End If Next Local newitem:TExternal= New TExternal newitem._Text=Text ExternalObjects.AddFirst(newitem) Print "Adding "+Text Return newitem.Handle() End Function Rem A Function to Delete the object when we are done with the handles and truely want to delete the object End Rem Function DeleteExternal(Handle:Int) For Local e:TExternal=EachIn ExternalObjects If e.Handle()=Handle ExternalObjects.Remove(e) Print "Deleting "+e._Text Return End If Next Throw "Unable to find item to delete" End Function Rem Test to see if our external string to handle works this just test the idea of external object manager than returns handles more than once if item already exists in collection or adds it if it doesnt End Rem 'Local a:Int=GetExternal("APPLE") 'Local b:Int=GetExternal("CHERRY") 'Local c:Int=GetExternal("APPLE") 'Print "a="+a 'Print "b="+b 'Print "c="+c 'DeleteExternal(a) 'DeleteExternal(b) 'DeleteExternal(c) ' This will throw since item does not exists Rem Here is the implementation to manage this. It uses a TMap with a special Type to manage reference counting of the instance of the Handle given out. When that count reachs zero it will remove object from the map and delete the external object End Rem Rem This object is used to manage the handles we have already gotten with a TMAP. Since TMAP requires object we can make it use the key and behavior by overriding the Compare Method End Rem Type THandle Field _handle:Int Method Compare:Int(o:Object) Return _handle-THandle(o)._handle End Method Function Create:THandle(Handle:Int) Local t:THandle t=New THandle t._handle=Handle Return t End Function End Type Rem This is the Type we use to reference count the external items End Rem Type TExternalMapItem Global _Map:TMap= New TMap Field _Handle:Int Field _RefCount:Int Method AddRef() _RefCount:+1 End Method Method ReleaseRef() _RefCount:-1 If _RefCount= 0 DeleteExternal(_Handle) _Map.Remove(THandle.Create(_Handle)) _Handle=0 End If End Method Function GetExternalMapItem:TExternalMapItem(Text:String) ' create a Thandle Local key:THandle= THandle.Create(GetExternal(Text)) ' if the Thandle is in the map we just add a reference ' otherwise we insert it in map and add reference Local mapitem:TExternalMapItem= TExternalMapItem(_Map.ValueForKey(key)) If (mapitem=Null) mapitem=New TExternalMapItem mapitem._handle=key._handle _Map.Insert(key,mapitem) End If mapitem.AddRef() Return mapitem End Function End Type Rem This is the wrapped item. we implement a Dispose method if we want to ensure deletion before Delete is called since we cant control when the GC will clean up this takes care safely wacking it, under our control or GC control. End Rem Type TExternalWrapper Field _ExternalMapItem:TExternalMapItem Method Handle:Int() Return _ExternalMapItem._Handle End Method Method Dispose() If _ExternalMapItem _ExternalMapItem.ReleaseRef() _ExternalMapItem=Null End Method Method Delete() Dispose() End Method ' our Create function for the wrapper Function Create:TExternalWrapper(Text:String) Local wrapper:TExternalWrapper= New TExternalWrapper wrapper._ExternalMapItem=TExternalMapItem.GetExternalMapItem(Text) Return wrapper End Function End Type Global a:TExternalWrapper=TExternalWrapper.Create("APPLE") Global b:TExternalWrapper=TExternalWrapper.Create("CHERRY") Global c:TExternalWrapper=TExternalWrapper.Create("APPLE") Print "a's Handle ="+a.Handle() Print "b's Handle ="+b.Handle() Print "c's Handle ="+c.Handle() b=Null a=Null Print "Before GCCollect Only CHERRY should be released" GCCollect() c=Null Print "Before GCCollect Only APPLE should be released" GCCollect() Global d:TExternalWrapper=TExternalWrapper.Create("PEAR") Print "d's Handle ="+d.Handle() Print "Force Deletion" d.Dispose() Print "Gone!" d=Null Print "Before GCCollect nothing will happen" GCCollect() Print "See nothing happend since we already disposed" Print "Done"
Maybe it will help, good luck
Doug Stastny