Singleton: Difference between revisions

Content added Content deleted
(added Caché ObjectScript)
Line 304: Line 304:
///
///
/// <EXAMPLE>
/// <EXAMPLE>
/// Set one=##class(Singleton).Get(.sc)
/// Set one=##class(Singleton).Get(,.sc)
/// Set one.GlobalProperty="Some Value"
/// Set one.GlobalProperty="Some Value"
/// Set sc=one.Set()
/// Set sc=one.Set()
/// </EXAMPLE>
/// </EXAMPLE>
///
///
/// This class can also be extended.
/// <p>Please be aware the 'Set' method will only work if no other process has the
/// global singleton object loaded. This class can also be extended.
Class User.Singleton Extends %SerialObject
Class User.Singleton Extends %SerialObject
{
{
Line 316: Line 315:
Property GlobalProperty As %String;
Property GlobalProperty As %String;


/// Refer to <LINK href=/AboutConcurrency.html>About Concurrency</LINK> for more details
ClassMethod Get(Output pStatus As %Status) As Singleton
/// on the optional <var>pConcurrency</var> argument.
ClassMethod Get(pConcurrency As %Integer = -1, Output pStatus As %Status = {$$$OK}) As Singleton
{
{
// check if singleton object already instantiated
// check if singleton object already instantiated
Line 324: Line 325:
If oRef.%ClassName(1) = ..%ClassName(1) Quit
If oRef.%ClassName(1) = ..%ClassName(1) Quit
}
}
If $IsObject(oRef) Set pStatus = $$$OK Quit oRef
If $IsObject(oRef) Quit oRef
// obtain shared lock for global singleton object
// determine what lock needs to be applied
If '$IsValidNum(pConcurrency, 0, -1, 4) {
Lock +^CacheTempUser("Singleton", ..%ClassName(1))#"S":1
Set pStatus = $$$ERROR($$$LockTypeInvalid, pConcurrency)
If '$Test {
Quit $$$NULLOREF
Set pStatus = $$$ERROR($$$GeneralError, "Exclusively locked by another process.")
}
If pConcurrency = -1 Set pConcurrency=$xecute("Quit "_..#DEFAULTCONCURRENCY)
// acquire lock for global singleton object
Set lockTO = $ZUtil(115,4), lockOK = 1
If (pConcurrency = 1) || (pConcurrency = 2) || (pConcurrency = 3) {
Lock +^CacheTempUser("Singleton", ..%ClassName(1))#"S":lockTO
Set lockOK = $Test
} ElseIf pConcurrency = 4 {
Lock +^CacheTempUser("Singleton", ..%ClassName(1)):lockTO
Set lockOK = $Test
}
If 'lockOK {
If pConcurrency=4 {
Set pStatus = $$$ERROR($$$LockFailedToAcquireExclusive, ..%ClassName(1))
} Else {
Set pStatus = $$$ERROR($$$LockFailedToAcquireRead, ..%ClassName(1))
}
Quit $$$NULLOREF
Quit $$$NULLOREF
}
}
Line 337: Line 356:
Set oRef = ..%Open(oId,, .pStatus)
Set oRef = ..%Open(oId,, .pStatus)
// release shared lock if object cannot be opened
// release temporary lock
If (pConcurrency = 1) || (pConcurrency = 2) {
If $$$ISERR(pStatus) {
Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S"
Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S"
}
// singleton object failed to load
If $$$ISERR(pStatus) {
// release retained lock
If pConcurrency = 3 {
Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S"
}
If pConcurrency = 4 {
Lock -^CacheTempUser("Singleton", ..%ClassName(1))
}
Quit $$$NULLOREF
Quit $$$NULLOREF
}
}
// return in-memory object referernce
// store concurrency state and return in-memory object reference
Set oRef.Concurrency = pConcurrency
Quit oRef
Quit oRef
}
}
Line 354: Line 385:
// obtain exclusive lock on global singleton object
// obtain exclusive lock on global singleton object
If ..Concurrency '= 0 {
Lock +^CacheTempUser("Singleton", ..%ClassName(1)):1
Set lockTO = $ZUtil(115,4)
If '$Test {
Lock +^CacheTempUser("Singleton", ..%ClassName(1)):lockTO
Quit $$$ERROR($$$GeneralError, "Can't save singleton object, locked by another process.")
If '$Test Quit $$$ERROR($$$LockFailedToAcquireExclusive, ..%ClassName(1))
}
}
// update global singleton object and release lock
// update global singleton object and release lock
Set ^CacheTempUser("Singleton", ..%ClassName(1)) = oId
Set ^CacheTempUser("Singleton", ..%ClassName(1)) = oId
If ..Concurrency '= 0 {
Lock -^CacheTempUser("Singleton", ..%ClassName(1))
Lock -^CacheTempUser("Singleton", ..%ClassName(1))
Quit $$$OK
}
}

Method %OnClose() As %Status [ Internal ]
{
// reference count for singleton object is now zero, so
// release shared lock on global singleton object
Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S"
Quit $$$OK
Quit $$$OK
}
}
Line 384: Line 410:
Quit $$$ERROR($$$GeneralError, "Can't clone instance.")
Quit $$$ERROR($$$GeneralError, "Can't clone instance.")
}
}

Method %OnClose() As %Status [ Internal ]
{
// reference count for singleton object is now zero, so
// release lock on global singleton object, if applicable
If ..Concurrency = 3 Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S"
If ..Concurrency = 4 Lock -^CacheTempUser("Singleton", ..%ClassName(1))
Quit $$$OK
}

Property Concurrency As %Integer [ Private, Transient ];


}
}