123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- 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.
-
- The reference count for a resource is initially 0.
-
- #end
- Method New()
- _live.Push( Self )
- 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 )
-
- _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 Discard()
- 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 _depends Return
-
- For Local r:=Eachin _depends
- r.Release()
- Next
-
- _depends=Null
- 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>
-
- _depends.Add( resource )
-
- resource.Retain()
- End
- #rem monkeydoc @hidden
- #end
- Function NumLive:Int()
-
- Return _live.Length
- 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>
- 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
- End
-
- Method OpenResource:Resource( slug:String )
-
- For Local manager:=Eachin _managers
-
- Local r:=manager._retained[slug]
- If Not r Continue
-
- If manager<>Self AddResource( slug,r )
-
- Return r
- Next
- Return Null
- 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
-
- _retained[slug]=r
-
- AddDependancy( r )
- End
-
- Protected
-
- Method OnDiscard() Override
-
- _managers.Remove( Self )
-
- _retained=Null
- End
-
- Private
-
- Global _managers:Stack<ResourceManager>
-
- Field _retained:=New StringMap<Resource>
- End
|