; From: Dat Thuc Nguyen
; Date: Wed, 23 Jun 1999 20:38:06 +0000
; Subject: Incoming Script - singleton.ksc
; URL: http://www.smalltickle.com
;
; IN THE PATTERNS COMMUNITY, THE SINGLETON IS A CLASS THAT CAN
; HAVE ONLY ONE INSTANCE.  ALL OBJECTS INSTANTIATED FROM THAT
; CLASS REFER TO THE ONE AND ONLY SINGLETON!
;
; THE SINGLETON IS VERY USEFUL WHERE THERE IS ONLY ONE RESOURCE
; AVAILABLE AND VARIOUS USER-DEFINED FUNCTIONS ACCESS THAT
; RESOURCE UNDER DIFFERENT REFFERENCES.
;
; THE SINGLETON CLASS ENSURES THAT ONE AND ONLY ONE OBJECT CAN BE
; INSTANTIATED FROM IT, THOUGH UNDER DIFFERENT NAMES.
; THE FOLLOWING SCRIPT DEFINES A SINGLETON CLASS.

;********************************************************
;    DEFINITION OF THE SINGLETON CLASS                  *
;********************************************************
define singleton {
    if NOT define \m(singleton::singleton) {
	assign singleton::singleton 0
    }

    _define \%1 {
        singleton::\%1 \v(macro)
    }
}

;******************************************************
;    IMPLEMENTATION OF THE PUBLIC USAGE INTERFACE     *
;    OF THE SEMAPHORE CLASS                           *
;******************************************************

; Smalltalk syntax
define singleton::up {
    assign singleton::singleton \feval(\m(singleton::singleton) + 1)
    echo   \m(singleton::singleton)
}

define singleton::down {
    assign singleton::singleton \feval(\m(singleton::singleton) - 1)
    echo   \m(singleton::singleton)
}

define singleton::query {
    echo   \m(singleton::singleton)
    return \m(singleton::singleton)
}

; C++ syntax
define singleton::++ {
    assign singleton::singleton \feval(\m(singleton::singleton) + 1)
    echo \m(singleton::singleton)
}

define singleton::-- {
    assign singleton::singleton \feval(\m(singleton::singleton) - 1)
    echo \m(singleton::singleton)
}

;********************************************************
;    USAGE SAMPLES					*
;********************************************************

take singleton.ksc

; In a user-defined function:
singleton printer			; create a singleton for printer
					; there is only one printer !!!

if = \fexec(printer query) 0 {		; if printer is available
    printer up			        ; register for printer
    do_some_processing			; 
    printer down			; release printer
}
;
;
; In another user-defined function
singleton my_printer			; refer always to the same singleton
                                        ; as the printer above
if = \fexec(my_printer query) 0 {	; if printer is available
	my_printer up			: Register for printer
	do_some_processing		; 
	my_printer down			; release printer
}

; EXPERIMENT
;
for \%i 1 10 1 { printer up }
printer query			; 'printer query' and 'my_printer query'
my_printer query		; produce the same result, that's singleton
