Axon.st 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. Smalltalk createPackage: 'Axon'!
  2. Object subclass: #Axon
  3. instanceVariableNames: 'factory'
  4. package: 'Axon'!
  5. !Axon commentStamp!
  6. I represent a pub-sub based on a key (called 'aspect').
  7. I manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.
  8. The interest objects are responsible of decision if the change of an aspect is relevant for them.
  9. Interest object must be subclasses of `AxonInterest`.
  10. My subclasses must provide implementation for:
  11. - add:
  12. - do:
  13. - clean!
  14. !Axon methodsFor: 'action'!
  15. addInterest: anInterest
  16. self
  17. add: (anInterest flag; yourself);
  18. dirty: true
  19. !
  20. changed: anAspect
  21. | needsToRun |
  22. needsToRun := false.
  23. self do: [ :each |
  24. (each accepts: anAspect) ifTrue: [
  25. each flag.
  26. needsToRun := true ]].
  27. self dirty: needsToRun
  28. !
  29. changedAll
  30. | needsToRun |
  31. needsToRun := false.
  32. self do: [ :each |
  33. each flag.
  34. needsToRun := true ].
  35. self dirty: needsToRun
  36. !
  37. dirty: aBoolean
  38. aBoolean ifTrue: [[ self run ] fork]
  39. !
  40. run
  41. [
  42. | needsClean |
  43. needsClean := false.
  44. self do: [ :each |
  45. each isFlagged ifTrue: [ each run ].
  46. each isEnabled ifFalse: [ needsClean := true ]
  47. ].
  48. needsClean ifTrue: [ self clean ]
  49. ] on: Error do: [ self dirty: true ]
  50. ! !
  51. Axon subclass: #SimpleAxon
  52. instanceVariableNames: 'queue'
  53. package: 'Axon'!
  54. !SimpleAxon methodsFor: 'accessing'!
  55. add: aSubscription
  56. queue add: aSubscription.
  57. ! !
  58. !SimpleAxon methodsFor: 'bookkeeping'!
  59. clean
  60. queue := queue select: [ :each | each isEnabled ]
  61. ! !
  62. !SimpleAxon methodsFor: 'enumeration'!
  63. do: aBlock
  64. queue do: aBlock
  65. ! !
  66. !SimpleAxon methodsFor: 'initialization'!
  67. initialize
  68. super initialize.
  69. queue := OrderedCollection new
  70. ! !
  71. Object subclass: #AxonInterest
  72. instanceVariableNames: 'aspect actionBlock flagged'
  73. package: 'Axon'!
  74. !AxonInterest methodsFor: 'accessing'!
  75. aspect: anAspect block: aBlock
  76. aspect := anAspect.
  77. actionBlock := aBlock
  78. !
  79. flag
  80. flagged := true
  81. ! !
  82. !AxonInterest methodsFor: 'action'!
  83. run
  84. [ flagged := false. actionBlock value ]
  85. on: AxonOff do: [ actionBlock := nil ]
  86. ! !
  87. !AxonInterest methodsFor: 'initialization'!
  88. initialize
  89. super initialize.
  90. aspect := nil.
  91. actionBlock := nil.
  92. flagged := false.
  93. ! !
  94. !AxonInterest methodsFor: 'testing'!
  95. accepts: anAspect
  96. "Should return true if change for anAspect is relevant for this AxonInterest"
  97. self subclassResponsibility
  98. !
  99. isEnabled
  100. ^actionBlock notNil
  101. !
  102. isFlagged
  103. ^flagged
  104. ! !
  105. AxonInterest subclass: #InterestedInEqual
  106. instanceVariableNames: ''
  107. package: 'Axon'!
  108. !InterestedInEqual methodsFor: 'testing'!
  109. accepts: anAspect
  110. ^ anAspect = aspect
  111. ! !
  112. Error subclass: #AxonOff
  113. instanceVariableNames: ''
  114. package: 'Axon'!
  115. !AxonOff commentStamp!
  116. Signal me from the subscription block to unsubscribe it.!
  117. Object subclass: #AxonizedObject
  118. instanceVariableNames: 'axon'
  119. package: 'Axon'!
  120. !AxonizedObject commentStamp!
  121. I am base class for object using Axon changed:
  122. for event / change logistics,
  123. Set Axon instance with `axon:` and then use
  124. `self changed: anAspect` to trigger axon's `changed:`.!
  125. !AxonizedObject methodsFor: 'accessing'!
  126. axon
  127. ^ axon
  128. !
  129. axon: anAxon
  130. axon := anAxon
  131. ! !
  132. !AxonizedObject methodsFor: 'action'!
  133. changed: anAspect
  134. self axon changed: anAspect
  135. ! !