Skip to content

Commit

Permalink
[feenkcom/gtoolkit#3703] add AsyncForkPollFuture
Browse files Browse the repository at this point in the history
  • Loading branch information
syrel committed Mar 27, 2024
1 parent 88abf77 commit 0480cac
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/Futures/AsyncForkPollFuture.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"
An alternative to {{gtClass:AsyncPollFuture}} but executes a {{gtClass:BlockClosure}} in its own forked process.
"
Class {
#name : #AsyncForkPollFuture,
#superclass : #Object,
#traits : 'TAsyncFuture',
#classTraits : 'TAsyncFuture classTrait',
#instVars : [
'pollBlock',
'executedBlock',
'computationProcess',
'computationValue',
'waker'
],
#category : #'Futures-Base - Futures'
}

{ #category : #'instance creation' }
AsyncForkPollFuture class >> pollBlock: aBlock [
^ self new pollBlock: aBlock
]

{ #category : #accessing }
AsyncForkPollFuture >> initialize [
super initialize.

computationValue := AsyncMutex for: AsyncOptionalValue none.
computationProcess := AsyncMutex for: AsyncOptionalValue none.
waker := AsyncFutureExecutionAtomicWaker new
]

{ #category : #'api - future' }
AsyncForkPollFuture >> poll: anAsynchronousContext [
computationValue lock: [ :aValueOption |
aValueOption
ifSome: [ :aValue |
computationValue value: AsyncOptionalValue none.
^ AsyncPoll ready: aValue ] ].

computationProcess lock: [ :aProcessOption |
aProcessOption
ifSome: [ :aProcess |
waker register: anAsynchronousContext waker.
^ AsyncPoll pending ] ].

self
assert: [ pollBlock notNil ]
description: [ 'Block already polled' ].

executedBlock := pollBlock.
pollBlock := nil.
computationProcess value: ([
computationValue value: (AsyncOptionalValue some: executedBlock value).
computationProcess value: (AsyncOptionalValue none).
waker wakeUp
] newProcess).

waker register: anAsynchronousContext waker.
computationProcess value resume.
^ AsyncPoll pending
]

{ #category : #initialization }
AsyncForkPollFuture >> pollBlock: aBlock [
pollBlock := aBlock.
executedBlock := nil
]

{ #category : #'api - future copy' }
AsyncForkPollFuture >> postSimilarCopy [
"Is called by similarCopy. self is a shallow copy, implementors should set the fields as necessary to complete the similar copy"

computationValue := AsyncMutex for: AsyncOptionalValue none.
computationProcess := AsyncMutex for: AsyncOptionalValue none.
waker := AsyncFutureExecutionAtomicWaker new.

executedBlock ifNotNil: [ pollBlock := executedBlock ].
executedBlock := nil
]
5 changes: 5 additions & 0 deletions src/Futures/BlockClosure.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Extension { #name : #BlockClosure }

{ #category : #'*Futures' }
BlockClosure >> asAsyncForkedFuture [
^ AsyncForkPollFuture pollBlock: self
]

{ #category : #'*Futures' }
BlockClosure >> asAsyncFuture [
^ AsyncPollFuture pollBlock: self
Expand Down

0 comments on commit 0480cac

Please sign in to comment.