Tips & Tricks - Process-private Globals as a class storage
Process-private Globals can be used as a data global in storage definition. That way, each process can have its own objects for the class with ppg storage. For example lets define a pool, which can:
- add elements to a pool (ignoring duplicates)
- check if an element exists in the pool
Here's the class:
/// Stores unique identifiers Class Utils.Pool Extends %Persistent { Property Value As %String; Index IDKEY On Value [ IdKey, PrimaryKey, Unique ]; Method %OnNew(Value As %String = "") As %Status [ Private, ServerOnly = 1 ] { Set ..Value = Value Quit $$$OK } ClassMethod Add(Value As %String = "") { Quit:..%ExistsId(Value) Set Obj = ..%New(Value) Do Obj.%Save() } Storage Default { <Data name="PoolDefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> </Data> <DataLocation>^||Utils.PoolD</DataLocation> <DefaultData>PoolDefaultData</DefaultData> <IdLocation>^||Utils.PoolD</IdLocation> <IndexLocation>^||Utils.PoolI</IndexLocation> <StreamLocation>^||Utils.PoolS</StreamLocation> <Type>%Library.CacheStorage</Type> } }
And the testing code:
/// Do ##class(Utils.Pool).Test() ClassMethod Test() { Do ..%KillExtent() Do ..Add(1) Write "Is 1 in pool: ", ..%ExistsId(1),! Write "Is 2 in pool: ", ..%ExistsId(2),! Do ..Add(2) Write "Is 2 in pool: ", ..%ExistsId(2),! }
Outputs:
Is 1 in pool: 1 Is 2 in pool: 0 Is 2 in pool: 1
This approach can be used if you want:
- Storage space, inaccessible to other processes (without using locks, etc)
- Store something only while process lives
The code is also available on GitHub.