|
@@ -1,187 +1,64 @@
|
|
|
|
|
|
Namespace std.resource
|
|
|
|
|
|
-#rem
|
|
|
-
|
|
|
-Ok, the basic rules for resource management are:
|
|
|
-
|
|
|
-* If you create a resource using 'New' or 'Load', you must either Retain() it, Discard() it or add it as a dependancy of another resource (same as retaining it really).
|
|
|
-
|
|
|
-* If you Retain() a resource, you must eventually Release() it.
|
|
|
-
|
|
|
-* If you open a resource from a resource manager using an OpenBlah method, it will be managed for you.
|
|
|
-
|
|
|
-* Discarding() a resource manager releases any resources it is managing.
|
|
|
-
|
|
|
-Note:
|
|
|
-
|
|
|
-AddDependancy( r1,r2 ) is pretty much the same as:
|
|
|
-
|
|
|
-r2.Retain()
|
|
|
-r1.OnDiscarded+=Lambda()
|
|
|
- r2.Release()
|
|
|
-End
|
|
|
-
|
|
|
-Implemented as a stack for now so I can debug it.
|
|
|
-
|
|
|
-#end
|
|
|
-
|
|
|
Class Resource
|
|
|
-
|
|
|
- #rem monkeydoc Invoked when the resource is discarded.
|
|
|
- #end
|
|
|
- Field OnDiscarded:Void()
|
|
|
|
|
|
- #rem monkeydoc Creates a new resource.
|
|
|
+ Field Discarded:Void()
|
|
|
|
|
|
- The reference count for a resource is initially 0.
|
|
|
-
|
|
|
- #end
|
|
|
- Method New()
|
|
|
-
|
|
|
- _live.Push( Self )
|
|
|
+ Property Refs:Int()
|
|
|
+
|
|
|
+ Return _refs
|
|
|
End
|
|
|
|
|
|
- #rem monkeydoc True if resource has been discarded.
|
|
|
- #end
|
|
|
- Property Discarded:Bool()
|
|
|
-
|
|
|
- Return _refs=-1
|
|
|
- End
|
|
|
-
|
|
|
- #rem monkeydoc Retains the resource.
|
|
|
-
|
|
|
- Increments the resource's reference count by 1.
|
|
|
-
|
|
|
- Resources with a reference counter >0 will not be discarded.
|
|
|
-
|
|
|
- #end
|
|
|
Method Retain()
|
|
|
- DebugAssert( _refs>=0 )
|
|
|
+
|
|
|
+ If Not _refs Return
|
|
|
|
|
|
_refs+=1
|
|
|
End
|
|
|
|
|
|
- #rem monkeydoc Releases the resource.
|
|
|
-
|
|
|
- Decrements the resource's reference count by 1.
|
|
|
-
|
|
|
- If the reference count becomes 0, the resource is discarded.
|
|
|
-
|
|
|
- #end
|
|
|
Method Release()
|
|
|
-
|
|
|
- DebugAssert( _refs>0 )
|
|
|
|
|
|
- _refs-=1
|
|
|
+ If Not _refs Return
|
|
|
|
|
|
- If Not _refs Discard()
|
|
|
+ If _refs=1 Discard() Else _refs-=1
|
|
|
End
|
|
|
|
|
|
- #rem monkeydoc Discards the resource.
|
|
|
-
|
|
|
- If the resource's reference count is >0 or the resource has already been discarded, nothing happens.
|
|
|
-
|
|
|
- If the resource's reference count is 0, the resource is discarded. First, OnDiscard() is called, then OnDiscarded() and finally any dependancies are released.
|
|
|
-
|
|
|
- #end
|
|
|
Method Discard()
|
|
|
- If _refs Return
|
|
|
-
|
|
|
- _refs=-1
|
|
|
-
|
|
|
- _live.Remove( Self )
|
|
|
-
|
|
|
- OnDiscard()
|
|
|
|
|
|
- OnDiscarded()
|
|
|
+ If Not _refs Return
|
|
|
|
|
|
- If Not _depends Return
|
|
|
+ _refs=0
|
|
|
|
|
|
- For Local r:=Eachin _depends
|
|
|
- r.Release()
|
|
|
- Next
|
|
|
+ OnDiscard()
|
|
|
|
|
|
- _depends=Null
|
|
|
+ Discarded()
|
|
|
End
|
|
|
|
|
|
- #rem monkeydoc Adds a dependancy to the resource.
|
|
|
-
|
|
|
- Adds `resource` to the list of dependancies for this resource and retains it.
|
|
|
-
|
|
|
- When this resource is eventually discarded, `resource` will be automatically released.
|
|
|
-
|
|
|
- #end
|
|
|
- Method AddDependancy( resource:Resource )
|
|
|
- DebugAssert( _refs>=0 And resource._refs>=0 )
|
|
|
-
|
|
|
- If Not _depends _depends=New Stack<Resource>
|
|
|
+ Method AddDependancy( r:Resource )
|
|
|
|
|
|
- _depends.Add( resource )
|
|
|
+ If Not r Return
|
|
|
|
|
|
- resource.Retain()
|
|
|
- End
|
|
|
+ r.Retain()
|
|
|
|
|
|
- #rem monkeydoc @hidden
|
|
|
- #end
|
|
|
- Function NumLive:Int()
|
|
|
-
|
|
|
- Return _live.Length
|
|
|
+ Discarded+=r.Release
|
|
|
End
|
|
|
|
|
|
Protected
|
|
|
|
|
|
- #rem monkeydoc Called when resource is discarded.
|
|
|
- #end
|
|
|
Method OnDiscard() Virtual
|
|
|
End
|
|
|
|
|
|
Private
|
|
|
|
|
|
- Global _live:=New Stack<Resource>
|
|
|
-
|
|
|
- Field _refs:Int
|
|
|
-
|
|
|
- Field _depends:Stack<Resource>
|
|
|
+ Field _refs:=1
|
|
|
End
|
|
|
|
|
|
Class ResourceManager Extends Resource
|
|
|
|
|
|
Method New()
|
|
|
- If Not _managers
|
|
|
- _managers=New Stack<ResourceManager>
|
|
|
- Endif
|
|
|
- _managers.Push( Self )
|
|
|
- End
|
|
|
-
|
|
|
- Function DebugDeps( r:Resource,indent:String )
|
|
|
-
|
|
|
- If Not r._depends Return
|
|
|
-
|
|
|
- indent+=" "
|
|
|
- For Local d:=Eachin r._depends
|
|
|
- Print indent+String.FromCString( d.typeName() )+", refs="+d._refs
|
|
|
- DebugDeps( d,indent )
|
|
|
- Next
|
|
|
- indent=indent.Slice( 0,-2 )
|
|
|
-
|
|
|
- End
|
|
|
-
|
|
|
- Function DebugAll()
|
|
|
-
|
|
|
- For Local manager:=Eachin _managers
|
|
|
-
|
|
|
- For Local it:=Eachin manager._retained
|
|
|
-
|
|
|
- Print it.Key+", refs="+it.Value._refs
|
|
|
- DebugDeps( it.Value,"" )
|
|
|
|
|
|
- Next
|
|
|
- Next
|
|
|
-
|
|
|
- For Local r:=Eachin _live
|
|
|
- 'If Not r._slug Print String.FromCString( r.typeName() )+", ref="+r._refs+", slug="+r._slug
|
|
|
- End
|
|
|
+ _managers.Push( Self )
|
|
|
End
|
|
|
|
|
|
Method OpenResource:Resource( slug:String )
|
|
@@ -189,6 +66,7 @@ Class ResourceManager Extends Resource
|
|
|
For Local manager:=Eachin _managers
|
|
|
|
|
|
Local r:=manager._retained[slug]
|
|
|
+
|
|
|
If Not r Continue
|
|
|
|
|
|
If manager<>Self AddResource( slug,r )
|
|
@@ -200,15 +78,10 @@ Class ResourceManager Extends Resource
|
|
|
End
|
|
|
|
|
|
Method AddResource( slug:String,r:Resource )
|
|
|
- If Not r Return
|
|
|
-
|
|
|
- DebugAssert( Not r.Discarded,"Can't add discarded resource to resource manager" )
|
|
|
|
|
|
- If _retained.Contains( slug ) Return
|
|
|
+ If Not r Or _retained.Contains( slug ) Return
|
|
|
|
|
|
_retained[slug]=r
|
|
|
-
|
|
|
- AddDependancy( r )
|
|
|
End
|
|
|
|
|
|
Protected
|
|
@@ -216,14 +89,33 @@ Class ResourceManager Extends Resource
|
|
|
Method OnDiscard() Override
|
|
|
|
|
|
_managers.Remove( Self )
|
|
|
-
|
|
|
+
|
|
|
+ For Local it:=Eachin _retained
|
|
|
+
|
|
|
+ it.Value.Release()
|
|
|
+
|
|
|
+ it.Value=Null
|
|
|
+ Next
|
|
|
+
|
|
|
_retained=Null
|
|
|
End
|
|
|
|
|
|
Private
|
|
|
|
|
|
- Global _managers:Stack<ResourceManager>
|
|
|
+ Global _managers:=New Stack<ResourceManager>
|
|
|
+
|
|
|
+ Global _refs:=New StringMap<Int>
|
|
|
|
|
|
Field _retained:=New StringMap<Resource>
|
|
|
|
|
|
End
|
|
|
+
|
|
|
+Function SafeRetain( r:Resource )
|
|
|
+
|
|
|
+ If r r.Retain()
|
|
|
+End
|
|
|
+
|
|
|
+Function SafeRelease( r:Resource )
|
|
|
+
|
|
|
+ If r r.Release()
|
|
|
+End
|