Future.st
author Claus Gittinger <cg@exept.de>
Tue, 04 Oct 2011 14:55:22 +0200
changeset 2667 e65a29b55fe1
parent 2666 fb363ea60a10
child 2668 67b51e1ee66d
permissions -rw-r--r--
added: #priority:block:valueWithArguments: changed: #block:valueWithArguments:

"
 This is a Manchester Goodie protected by copyright.
 These conditions are imposed on the whole Goodie, and on any significant
 part of it which is separately transmitted or stored:
	* You must ensure that every copy includes this notice, and that
	  source and author(s) of the material are acknowledged.
	* These conditions must be imposed on anyone who receives a copy.
	* The material shall not be used for commercial gain without the prior
	  written consent of the author(s).
 Further information on the copyright conditions may be obtained by
 sending electronic mail:
	To: goodies-lib@cs.man.ac.uk
	Subject: copyright
 or by writing to The Smalltalk Goodies Library Manager, Dept of
 Computer Science, The University, Manchester M13 9PL, UK

 (C) Copyright 1992 University of Manchester
 For more information about the Manchester Goodies Library (from which
 this file was distributed) send e-mail:
	To: goodies-lib@cs.man.ac.uk
	Subject: help
"
"{ Package: 'stx:libbasic2' }"

ProtoObject subclass:#Future
	instanceVariableNames:'result semaphore'
	classVariableNames:''
	poolDictionaries:''
	category:'Kernel-Processes'
!

!Future class methodsFor:'documentation'!

copyright
"
 This is a Manchester Goodie protected by copyright.
 These conditions are imposed on the whole Goodie, and on any significant
 part of it which is separately transmitted or stored:
	* You must ensure that every copy includes this notice, and that
	  source and author(s) of the material are acknowledged.
	* These conditions must be imposed on anyone who receives a copy.
	* The material shall not be used for commercial gain without the prior
	  written consent of the author(s).
 Further information on the copyright conditions may be obtained by
 sending electronic mail:
	To: goodies-lib@cs.man.ac.uk
	Subject: copyright
 or by writing to The Smalltalk Goodies Library Manager, Dept of
 Computer Science, The University, Manchester M13 9PL, UK

 (C) Copyright 1992 University of Manchester
 For more information about the Manchester Goodies Library (from which
 this file was distributed) send e-mail:
	To: goodies-lib@cs.man.ac.uk
	Subject: help
"
!

documentation
"
    I represent an execution in progress.
    I will immediately start execution in a separate process.
    Any messages sent to me are delayed until execution has completed.'

    [author:]
	tph@cs.man.ac.uk

    [see also:]
	Block Lazy LazyValue
"
!

examples
"
  Starts evaluating the factorial immediately, but waits until
  the result is available before printing the answer
								    [exBegin]
    | fac |

    fac := [5000 factorial] futureValue.
    Transcript showCR: 'evaluating factorial...'.
    Transcript showCR: fac printString
								    [exEnd]


  An example illustrating the use of multiple futures and
  explicit resynchronisation.

  Starts evaluating both factorials immediately, but waits until
  both blocks have finished before continuing.
								    [exBegin]
    | fac1 fac2 |

    fac1 := [Transcript showCR: 'Starting fac1.. '. 1000 factorial] futureValue.
    fac2 := [Transcript showCR: 'Starting fac2.. '. 2000 factorial] futureValue.
    fac2 isString.
    fac1 isString.
    Transcript showCR: 'both completed.'.
								    [exEnd]

  Example showing how arguments may be passed to futures.
								    [exBegin]
    | temp |

    temp := [:x :y | 10 * x * y] futureValue: 3 value: 4.
    Transcript  showCR: temp printString.

								    [exEnd]

  Claus:
    The above examples do not really show the power of Futures;
    they can be useful, whenever some long-time computation is
    to be done, and some other useful work can be done in the meanwhile.
    for example:

    Here, the input is read before - the readTime and view creation
    times sum up:
								    [exBegin]
	|p text v|

	p := PipeStream readingFrom:'ls -l /bin /usr/bin /usr/lib'.
	text := p contents.
	p close.
	v := TextView new openAndWait.
	v contents:text
								    [exEnd]

    The same here:
								    [exBegin]
	|p text v|

	v := TextView new openAndWait.
	p := PipeStream readingFrom:'ls -l /bin /usr/bin /usr/lib'.
	text := p contents.
	p close.
	v contents:text
								    [exEnd]


    Here, the view creation and reading are done in parallel:
    (if the user is slow when opening the view, the contents may
     be already available)
								    [exBegin]
	|p text v|

	text := [   |p t|

		    p := PipeStream readingFrom:'ls -l /bin /usr/bin /usr/lib'.
		    t := p contents.
		    p close.
		    t
		] futureValue.
	v := TextView new openAndWait.
	v contents:text
								    [exEnd]
"
! !

!Future methodsFor:'evaluating'!

block:aBlock
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [result := aBlock ensure:[semaphore signal]] fork

    "Modified (format): / 04-10-2011 / 14:54:11 / cg"
!

block:aBlock value:aValue
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:aValue
        ] ensure:[semaphore signal]
    ] fork

    "Modified (format): / 04-10-2011 / 14:54:18 / cg"
!

block:aBlock value:value1 value:value2
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:value1 value:value2
        ] ensure:[semaphore signal]
    ] fork

    "Modified (format): / 04-10-2011 / 14:54:28 / cg"
!

block:aBlock value:value1 value:value2 value:value3
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:value1 value:value2 value:value3
        ] ensure:[semaphore signal]
    ] fork

    "Modified (format): / 04-10-2011 / 14:54:45 / cg"
!

block:aBlock valueWithArguments:anArray
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock valueWithArguments:anArray
        ] ensure:[semaphore signal]
    ] fork

    "Modified (format): / 04-10-2011 / 14:55:09 / cg"
!

priority:prio block: aBlock
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := aBlock ensure:[semaphore signal]
    ] forkAt:prio

    "Created: / 04-10-2011 / 14:53:21 / cg"
!

priority:prio block: aBlock value: aValue
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:aValue
        ] ensure:[semaphore signal]
    ] forkAt:prio

    "Created: / 04-10-2011 / 14:53:35 / cg"
!

priority:prio block:aBlock value:value1 value:value2
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:value1 value:value2
        ] ensure:[semaphore signal]
    ] forkAt:prio

    "Created: / 04-10-2011 / 14:54:03 / cg"
!

priority:prio block:aBlock value:value1 value:value2 value:value3
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock value:value1 value:value2 value:value3
        ] ensure:[semaphore signal]
    ] forkAt:prio

    "Created: / 04-10-2011 / 14:54:51 / cg"
!

priority:prio block:aBlock valueWithArguments:anArray
    "Execute aBlock in parallel with whatever called me, but
     ensure that any messages sent to me before execution
     of the block has terminated are suspended until it has terminated."

    semaphore := Semaphore new name:'Future'.
    [
        result := [
            aBlock valueWithArguments:anArray
        ] ensure:[semaphore signal]
    ] forkAt:prio

    "Created: / 04-10-2011 / 14:55:14 / cg"
! !

!Future methodsFor:'synchronising'!

doesNotUnderstand:aMessage
    "Any message to a Future will end up here."

    semaphore waitUncounted. "Wait for evaluation to complete"
			     "(if not already completed)"
    ^ result perform:aMessage selector withArguments:aMessage arguments
! !

!Future methodsFor:'testing'!

hasValue
    ^ semaphore wouldBlock not
!

isLazyValue
    ^ semaphore wouldBlock
! !

!Future class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic2/Future.st,v 1.13 2011-10-04 12:55:22 cg Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libbasic2/Future.st,v 1.13 2011-10-04 12:55:22 cg Exp $'
! !