Axxord-Axon.st 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. Smalltalk createPackage: 'Axxord-Axon'!
  2. Object subclass: #Axon
  3. instanceVariableNames: 'factory'
  4. package: 'Axxord-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: 'accessing'!
  15. addInterest: anInterest
  16. self
  17. add: (anInterest flag; yourself);
  18. dirty: true
  19. ! !
  20. !Axon methodsFor: 'change-update'!
  21. changed: anAspect
  22. | needsToRun |
  23. needsToRun := false.
  24. self do: [ :each |
  25. (each accepts: anAspect) ifTrue: [
  26. each flag.
  27. needsToRun := true ]].
  28. self dirty: needsToRun
  29. !
  30. changedAll
  31. | needsToRun |
  32. needsToRun := false.
  33. self do: [ :each |
  34. each flag.
  35. needsToRun := true ].
  36. self dirty: needsToRun
  37. ! !
  38. !Axon methodsFor: 'primitive ops'!
  39. add: anInterest
  40. self subclassResponsibility
  41. !
  42. clean
  43. self subclassResponsibility
  44. !
  45. do: aBlock
  46. self subclassResponsibility
  47. ! !
  48. !Axon methodsFor: 'private'!
  49. dirty: aBoolean
  50. aBoolean ifTrue: [[ self run ] fork]
  51. !
  52. run
  53. [
  54. | needsClean |
  55. needsClean := false.
  56. self do: [ :each |
  57. each isFlagged ifTrue: [ each run ].
  58. each isClosed ifTrue: [ needsClean := true ]
  59. ].
  60. needsClean ifTrue: [ self clean ]
  61. ] on: Error do: [ self dirty: true ]
  62. ! !
  63. Axon subclass: #SimpleAxon
  64. instanceVariableNames: 'queue'
  65. package: 'Axxord-Axon'!
  66. !SimpleAxon methodsFor: 'initialization'!
  67. initialize
  68. super initialize.
  69. queue := OrderedCollection new
  70. ! !
  71. !SimpleAxon methodsFor: 'primitive ops'!
  72. add: aSubscription
  73. queue add: aSubscription.
  74. !
  75. clean
  76. queue := queue reject: [ :each | each isClosed ]
  77. !
  78. do: aBlock
  79. queue do: aBlock
  80. ! !
  81. Object subclass: #AxonInterest
  82. instanceVariableNames: 'flagged'
  83. package: 'Axxord-Axon'!
  84. !AxonInterest methodsFor: 'accessing'!
  85. flag
  86. flagged := true
  87. ! !
  88. !AxonInterest methodsFor: 'action'!
  89. close
  90. self subclassResponsibility
  91. !
  92. enact
  93. self subclassResponsibility
  94. !
  95. run
  96. [ flagged := false. self enact ]
  97. on: AxonOff do: [ self close ]
  98. ! !
  99. !AxonInterest methodsFor: 'initialization'!
  100. initialize
  101. super initialize.
  102. flagged := false.
  103. ! !
  104. !AxonInterest methodsFor: 'testing'!
  105. accepts: anAspect
  106. "Should return true if change for anAspect is relevant for this AxonInterest"
  107. self subclassResponsibility
  108. !
  109. isClosed
  110. self subclassResponsibility
  111. !
  112. isFlagged
  113. ^flagged
  114. ! !
  115. AxonInterest subclass: #PluggableInterest
  116. instanceVariableNames: 'acceptBlock enactBlock'
  117. package: 'Axxord-Axon'!
  118. !PluggableInterest methodsFor: 'accessing'!
  119. accept: aBlock enact: anotherBlock
  120. acceptBlock := aBlock.
  121. enactBlock := anotherBlock
  122. ! !
  123. !PluggableInterest methodsFor: 'action'!
  124. close
  125. acceptBlock := nil.
  126. enactBlock := nil
  127. !
  128. enact
  129. enactBlock value
  130. ! !
  131. !PluggableInterest methodsFor: 'initialization'!
  132. initialize
  133. super initialize.
  134. self close
  135. ! !
  136. !PluggableInterest methodsFor: 'testing'!
  137. accepts: anAspect
  138. ^ acceptBlock value: anAspect
  139. !
  140. isClosed
  141. ^ acceptBlock isNil
  142. ! !
  143. Error subclass: #AxonOff
  144. instanceVariableNames: ''
  145. package: 'Axxord-Axon'!
  146. !AxonOff commentStamp!
  147. Signal me from the subscription block to unsubscribe it.!