123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- Smalltalk createPackage: 'Axon'!
- Object subclass: #Axon
- instanceVariableNames: 'factory'
- package: 'Axon'!
- !Axon commentStamp!
- I represent a pub-sub based on a key (called 'aspect').
- I manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.
- The interest objects are responsible of decision if the change of an aspect is relevant for them.
- Interest object must be subclasses of `AxonInterest`.
- My subclasses must provide implementation for:
- - add:
- - do:
- - clean!
- !Axon methodsFor: 'action'!
- addInterest: anInterest
- self
- add: (anInterest flag; yourself);
- dirty: true
- !
- changed: anAspect
- | needsToRun |
- needsToRun := false.
- self do: [ :each |
- (each accepts: anAspect) ifTrue: [
- each flag.
- needsToRun := true ]].
- self dirty: needsToRun
- !
- changedAll
- | needsToRun |
- needsToRun := false.
- self do: [ :each |
- each flag.
- needsToRun := true ].
- self dirty: needsToRun
- !
- dirty: aBoolean
- aBoolean ifTrue: [[ self run ] fork]
- !
- run
- [
- | needsClean |
- needsClean := false.
- self do: [ :each |
- each isFlagged ifTrue: [ each run ].
- each isEnabled ifFalse: [ needsClean := true ]
- ].
- needsClean ifTrue: [ self clean ]
- ] on: Error do: [ self dirty: true ]
- ! !
- Axon subclass: #SimpleAxon
- instanceVariableNames: 'queue'
- package: 'Axon'!
- !SimpleAxon methodsFor: 'accessing'!
- add: aSubscription
- queue add: aSubscription.
- ! !
- !SimpleAxon methodsFor: 'bookkeeping'!
- clean
- queue := queue select: [ :each | each isEnabled ]
- ! !
- !SimpleAxon methodsFor: 'enumeration'!
- do: aBlock
- queue do: aBlock
- ! !
- !SimpleAxon methodsFor: 'initialization'!
- initialize
- super initialize.
- queue := OrderedCollection new
- ! !
- Object subclass: #AxonInterest
- instanceVariableNames: 'aspect actionBlock flagged'
- package: 'Axon'!
- !AxonInterest methodsFor: 'accessing'!
- aspect: anAspect block: aBlock
- aspect := anAspect.
- actionBlock := aBlock
- !
- flag
- flagged := true
- ! !
- !AxonInterest methodsFor: 'action'!
- run
- [ flagged := false. actionBlock value ]
- on: AxonOff do: [ actionBlock := nil ]
- ! !
- !AxonInterest methodsFor: 'initialization'!
- initialize
- super initialize.
- aspect := nil.
- actionBlock := nil.
- flagged := false.
- ! !
- !AxonInterest methodsFor: 'testing'!
- accepts: anAspect
- "Should return true if change for anAspect is relevant for this AxonInterest"
- self subclassResponsibility
- !
- isEnabled
- ^actionBlock notNil
- !
- isFlagged
- ^flagged
- ! !
- AxonInterest subclass: #InterestedInEqual
- instanceVariableNames: ''
- package: 'Axon'!
- !InterestedInEqual methodsFor: 'testing'!
- accepts: anAspect
- ^ anAspect = aspect
- ! !
- Error subclass: #AxonOff
- instanceVariableNames: ''
- package: 'Axon'!
- !AxonOff commentStamp!
- Signal me from the subscription block to unsubscribe it.!
- Object subclass: #AxonizedObject
- instanceVariableNames: 'axon'
- package: 'Axon'!
- !AxonizedObject commentStamp!
- I am base class for object using Axon changed:
- for event / change logistics,
- Set Axon instance with `axon:` and then use
- `self changed: anAspect` to trigger axon's `changed:`.!
- !AxonizedObject methodsFor: 'accessing'!
- axon
- ^ axon
- !
- axon: anAxon
- axon := anAxon
- ! !
- !AxonizedObject methodsFor: 'action'!
- changed: anAspect
- self axon changed: anAspect
- ! !
|