Singleton: Difference between revisions
Content added Content deleted
(added Caché ObjectScript) |
|||
Line 292: | Line 292: | ||
// The rest of the methods |
// The rest of the methods |
||
}</lang> |
}</lang> |
||
=={{header|Caché ObjectScript}}== |
|||
In Caché, each job runs in a self-contained execution environment (i.e. a separate process instead of a thread). However, it is possible for each process to share data through multidimensional storage (global variables). This is because when the Caché virtual machine starts, it allocates a single, large chunk of shared memory to allow all Caché processes to access this data simultaneously. However, it is the responsibility of the application developer to ensure read and write access to objects is properly co-ordinated (or 'synchronized') between processes to prevent concurrency problems. Also, Caché defines any global variable whose name starts with 'CacheTemp' as being temporary, which means changes are not usually written to disk and are instead maintained within the in-memory buffer pool. |
|||
<lang cos> |
|||
/// The <CLASS>Singleton</CLASS> class represents a global singleton object that can |
|||
/// be instantiated by multiple processes. The 'Get' class method is used to obtain |
|||
/// an in-memory object reference and the 'Set' method is used to save any changes to |
|||
/// state. See below for an example. |
|||
/// |
|||
/// <EXAMPLE> |
|||
/// Set one=##class(Singleton).Get(.sc) |
|||
/// Set one.GlobalProperty="Some Value" |
|||
/// Set sc=one.Set() |
|||
/// </EXAMPLE> |
|||
/// |
|||
/// <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 |
|||
{ |
|||
Property GlobalProperty As %String; |
|||
ClassMethod Get(Output pStatus As %Status) As Singleton |
|||
{ |
|||
// check if singleton object already instantiated |
|||
Set oRef = "" |
|||
For { |
|||
Set oRef = $ZObjNext(oRef) If oRef = "" Quit |
|||
If oRef.%ClassName(1) = ..%ClassName(1) Quit |
|||
} |
|||
If $IsObject(oRef) Set pStatus = $$$OK Quit oRef |
|||
// obtain shared lock for global singleton object |
|||
Lock +^CacheTempUser("Singleton", ..%ClassName(1))#"S":1 |
|||
If '$Test { |
|||
Set pStatus = $$$ERROR($$$GeneralError, "Exclusively locked by another process.") |
|||
Quit $$$NULLOREF |
|||
} |
|||
// retrieve global singleton object and deserialise |
|||
Set oId = $Get(^CacheTempUser("Singleton", ..%ClassName(1))) |
|||
Set oRef = ..%Open(oId,, .pStatus) |
|||
// release shared lock if object cannot be opened |
|||
If $$$ISERR(pStatus) { |
|||
Lock -^CacheTempUser("Singleton", ..%ClassName(1))#"S" |
|||
Quit $$$NULLOREF |
|||
} |
|||
// return in-memory object referernce |
|||
Quit oRef |
|||
} |
|||
Method Set() As %Status |
|||
{ |
|||
// serialise local singleton object if changes have occurred |
|||
If ..%ObjectModified()=0 Quit $$$OK |
|||
Set sc = ..%GetSwizzleObject(,.oId) If $$$ISERR(sc) Quit sc |
|||
// obtain exclusive lock on global singleton object |
|||
Lock +^CacheTempUser("Singleton", ..%ClassName(1)):1 |
|||
If '$Test { |
|||
Quit $$$ERROR($$$GeneralError, "Can't save singleton object, locked by another process.") |
|||
} |
|||
// update global singleton object and release lock |
|||
Set ^CacheTempUser("Singleton", ..%ClassName(1)) = oId |
|||
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 |
|||
} |
|||
Method %OnNew() As %Status [ Internal ] |
|||
{ |
|||
// do not allow constructor method to be called |
|||
Quit $$$ERROR($$$GeneralError, "Can't instantiate directly.") |
|||
} |
|||
Method %OnConstructClone() As %Status [ Internal ] |
|||
{ |
|||
// do not allow singleton object to be cloned |
|||
Quit $$$ERROR($$$GeneralError, "Can't clone instance.") |
|||
} |
|||
} |
|||
</lang> |
|||
{{out|Examples}} |
|||
<pre> |
|||
USER>Set one=##class(Singleton).Get() |
|||
USER>Set one.GlobalProperty="Some Value" |
|||
USER>Set sc=one.Set() |
|||
</pre> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |