Promise.st
author Claus Gittinger <cg@exept.de>
Sat, 02 May 2020 21:40:13 +0200
changeset 5476 7355a4b11cb6
parent 5204 2aed622d96ee
permissions -rw-r--r--
#FEATURE by cg class: Socket class added: #newTCPclientToHost:port:domain:domainOrder:withTimeout: changed: #newTCPclientToHost:port:domain:withTimeout:

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic2' }"

"{ NameSpace: Smalltalk }"

Object subclass:#Promise
	instanceVariableNames:'value valueAvailable exception'
	classVariableNames:''
	poolDictionaries:''
	category:'Kernel-Processes'
!

!Promise class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    When created, a promise will start to evaluate its block in the background,
    and promise to deliver the value of this computation, when asked
    for it via #value. 
    If an exception happens druing the block evaluate,
    it will be delivered  to the value-consumer.

    Promises can be used for background computations,
    which automatically block the user of the result when that result is needed,
    unless the computation finished in the meanwhile.

    See also Block>>promise and Lazy/Future in libbasic2.
"
!

examples
"
     |p|

     p := [10000 factorial] promise.
     Transcript showCR:'doing something else'.
     p value   
"
! !

!Promise class methodsFor:'instance creation'!

new
    ^ self basicNew initialize 
!

value:aBlock
    "create and return a Promise to evaluate aBlock at the current priority"

    ^ self new value:aBlock priority:Processor activePriority 
!

value:aBlock priority:aPrio
    "create and return a Promise to evaluate aBlock at some priority"

    ^ self new value:aBlock priority:aPrio
! !

!Promise methodsFor:'accessing'!

value
    "return the value of the promise. 
     If the evaluation process has not yet finished, wait for it.
     Otherwise return the value immediately.
     Any exception which occurred during the evaluation is forwarded to the
     requestor of the value here."

    valueAvailable waitUncounted.
    exception notNil ifTrue:[
        "/
        "/ an exception occurred while evaluating the promise.
        "/ This exception is remembered and raised here, when the
        "/ value is asked for.
        "/ reRaise leaves the suspendedContext untouched.
        exception reRaise
    ].
    ^ value
!

value:anObject
    "fake value arrived"

    value := anObject.
    valueAvailable signal.

    "Modified: / 20-02-2017 / 10:28:23 / stefan"
! !

!Promise methodsFor:'initialization'!

initialize
    "setup"

    valueAvailable := EventSemaphore name:'Promise.valueAvailable'.

    "Modified: / 20-02-2017 / 10:37:40 / stefan"
!

value:aBlock priority:aPrio
    "setup and start the evaluation process."

    [
        |top|

        [
            top := thisContext.
            value := aBlock value.
        ] on:Error do:[:ex|
            "/ in order to be able to reRaise the exception 
            "/ AND provide the original walkback,
            "/ we make a special copy here.
            exception := ex copyWithWalkbackUpTo:top.
        ].
        valueAvailable signal.
    ] forkAt:aPrio

    "
     Promise value:[100 timesRepeat:[1000 factorial]] priority:7
    "
    "
     Promise value:[10 timesRepeat:[1000 factorial]. [self halt] value.] priority:7
    "

    "Modified: / 20-02-2017 / 10:31:36 / stefan"
! !

!Promise methodsFor:'queries'!

hasValue
    "return true, if the promise has a value available.
     (i.e. if sending #value to it would NOT block)"

    ^ valueAvailable wouldBlock not

    "Modified (comment): / 17-05-2017 / 16:57:53 / mawalch"
! !

!Promise class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !