Levente Uzonyi uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-ul.1152.mcz ==================== Summary ==================== Name: Morphic-ul.1152 Author: ul Time: 31 May 2016, 1:32:25.341018 am UUID: a2bb9c46-93c3-4586-84e3-7dff9fec4bd0 Ancestors: Morphic-ul.1151 Make MorphicAlarmQueue not be a subclass of Heap. Use encapsulation instead. Part #2. =============== Diff against Morphic-ul.1151 =============== Item was changed: + Object subclass: #MorphicAlarmQueue - Heap subclass: #MorphicAlarmQueue instanceVariableNames: 'mutex sequenceNumber heap' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Events'! !MorphicAlarmQueue commentStamp: 'jcg 1/9/2010 13:34' prior: 0! MorphicAlarmQueue is a specialized Heap. The main change is to stamp each added MorphicAlarm with a sequence number to ensure that alarms scheduled for the same time are executed in the order that they were added.! Item was changed: ----- Method: MorphicAlarmQueue>>add: (in category 'adding') ----- add: aMorphicAlarm + aMorphicAlarm sequenceNumber: self nextSequenceNumber. + ^heap add: aMorphicAlarm! - heap ifNotNil: [ - aMorphicAlarm sequenceNumber: self nextSequenceNumber. - ^heap add: aMorphicAlarm ]. - (sequenceNumber := sequenceNumber + 1) = 16r3FFFFFFF ifTrue: [ - "Sequence number overflow... reassign sequence numbers starting at 0." - | alarmList | - alarmList := self asArray sort: [:msg1 :msg2 | - msg1 sequenceNumber < msg2 sequenceNumber - ]. - alarmList withIndexDo: [:msg :ind | msg sequenceNumber: ind-1]. - "The #bitAnd: for the unlikely event that we have > 16r3FFFFFF messages in the queue." - sequenceNumber := alarmList last sequenceNumber + 1 bitAnd: 16r3FFFFFFF. - ]. - aMorphicAlarm sequenceNumber: sequenceNumber. - super add: aMorphicAlarm. - - "If we doubt our sanity..." - false ifTrue: [ - self isValidHeap ifFalse: [self error: 'not a valid heap!!!!!!']. - ]. - ^aMorphicAlarm! Item was added: + ----- Method: MorphicAlarmQueue>>alarmsDoSafely: (in category 'enumeration') ----- + alarmsDoSafely: aBlock + + heap asArray do: aBlock! Item was changed: ----- Method: MorphicAlarmQueue>>detect:ifNone: (in category 'migration') ----- detect: aBlock ifNone: noneBlock - heap ifNil: [ ^super detect: aBlock ifNone: noneBlock ]. ^heap detect: aBlock ifNone: noneBlock! Item was changed: ----- Method: MorphicAlarmQueue>>do: (in category 'migration') ----- do: aBlock - heap ifNil: [ ^super do: aBlock ]. ^heap do: aBlock! Item was changed: ----- Method: MorphicAlarmQueue>>first (in category 'migration') ----- first - heap ifNil: [ ^super first ]. ^heap first! Item was added: + ----- Method: MorphicAlarmQueue>>incrementScheduledTimesBy: (in category 'accessing') ----- + incrementScheduledTimesBy: anInteger + + heap do: [ :each | each scheduledTime: each scheduledTime + anInteger ]! Item was changed: ----- Method: MorphicAlarmQueue>>initialize (in category 'initialize') ----- initialize super initialize. + mutex := Mutex new. sequenceNumber := 0. heap := Heap sortBlock: [ :alarmA :alarmB | alarmA scheduledTime = alarmB scheduledTime ifFalse: [ alarmA scheduledTime < alarmB scheduledTime ] ifTrue: [ alarmA sequenceNumber = alarmB sequenceNumber ifFalse: [ alarmA sequenceNumber < alarmB sequenceNumber ] ifTrue: [ self error: 'These alarms run at the same time' ] ] ]! Item was changed: ----- Method: MorphicAlarmQueue>>isEmpty (in category 'migration') ----- isEmpty - heap ifNil: [ ^super isEmpty ]. ^heap isEmpty! Item was removed: - ----- Method: MorphicAlarmQueue>>isValidHeap (in category 'private') ----- - isValidHeap - "Verify the correctness of the heap" - 2 to: tally do:[:i| - (self sorts: (array at: i // 2) before: (array at: i)) ifFalse:[^false]. - ]. - ^true! Item was removed: - ----- Method: MorphicAlarmQueue>>migrate (in category 'migration') ----- - migrate - - heap ifNotNil: [ ^self ]. - heap := Heap withAll: self asArray sortBlock: [ :alarmA :alarmB | - alarmA scheduledTime = alarmB scheduledTime - ifFalse: [ alarmA scheduledTime < alarmB scheduledTime ] - ifTrue: [ - alarmA sequenceNumber = alarmB sequenceNumber - ifFalse: [ alarmA sequenceNumber < alarmB sequenceNumber ] - ifTrue: [ self error: 'These alarms run at the same time' ] ] ]! Item was changed: ----- Method: MorphicAlarmQueue>>mutex (in category 'accessing') ----- mutex + + ^mutex! - ^mutex ifNil: [mutex := Mutex new]! Item was changed: ----- Method: MorphicAlarmQueue>>nextSequenceNumber (in category 'private') ----- nextSequenceNumber (sequenceNumber := sequenceNumber + 1) = 16r3FFFFFFF ifTrue: [ "Sequence number overflow... reassign sequence numbers starting at 1." + heap fullySort. + 1 to: heap size do: [ :index | + (heap at: index) sequenceNumber: index ]. + sequenceNumber := heap size + 1 ]. - | alarmList | - alarmList := heap fullySort asArray. - alarmList withIndexDo: [ :alarm :index | - alarm sequenceNumber: index ]. - sequenceNumber := alarmList size + 1 ]. ^sequenceNumber! Item was changed: + ----- Method: MorphicAlarmQueue>>postCopy (in category 'copying') ----- - ----- Method: MorphicAlarmQueue>>postCopy (in category 'as yet unclassified') ----- postCopy super postCopy. heap := heap copy! Item was changed: ----- Method: MorphicAlarmQueue>>remove: (in category 'migration') ----- remove: anObject - heap ifNil: [ ^super remove: anObject ]. ^heap remove: anObject! Item was added: + ----- Method: MorphicAlarmQueue>>removeAlarmWithReceiver:selector: (in category 'removing') ----- + removeAlarmWithReceiver: receiver selector: selector + + heap + detect: [ :each | each receiver == receiver and: [ each selector == selector ] ] + ifFound: [ :found | heap remove: found ] + ifNone: [ ]! Item was added: + ----- Method: MorphicAlarmQueue>>removeAllAlarmsBefore: (in category 'removing') ----- + removeAllAlarmsBefore: nowTime + + ^Array new: 10 streamContents: [ :stream | + [ heap notEmpty and: [ heap first scheduledTime < nowTime ] ] + whileTrue: [ stream nextPut: heap removeFirst ] ]! Item was changed: ----- Method: MorphicAlarmQueue>>removeFirst (in category 'migration') ----- removeFirst - heap ifNil: [ ^super removeFirst ]. ^heap removeFirst! Item was removed: - ----- Method: MorphicAlarmQueue>>sorts:before: (in category 'comparing') ----- - sorts: alarmA before: alarmB - alarmA scheduledTime = alarmB scheduledTime - ifFalse:[^alarmA scheduledTime < alarmB scheduledTime]. - alarmA sequenceNumber = alarmB sequenceNumber - ifFalse:[^alarmA sequenceNumber < alarmB sequenceNumber]. - ^self error: 'These alarms run at the same time'! Item was changed: ----- Method: WorldState>>adjustAlarmTimes: (in category 'alarms') ----- adjustAlarmTimes: nowTime "Adjust the alarm times after some clock weirdness (such as roll-over, image-startup etc)" + | deltaTime | + (deltaTime := nowTime - lastAlarmTime) = 0 ifTrue: [ ^self ]. + self lockAlarmsDuring: [ :locked | locked incrementScheduledTimesBy: deltaTime ]! - deltaTime := nowTime - lastAlarmTime. - self lockAlarmsDuring: [:locked | - locked do:[:alarm| alarm scheduledTime: alarm scheduledTime + deltaTime]. - ]! Item was changed: ----- Method: WorldState>>cleanseStepListForWorld: (in category 'stepping') ----- cleanseStepListForWorld: aWorld "Remove morphs from the step list that are not in this World. Often were in a flap that has moved on to another world." + | deletions | - | deletions morphToStep | deletions := nil. stepList do: [:entry | + entry receiver world == aWorld ifFalse: [ + (deletions ifNil: [ deletions := OrderedCollection new ]) + addLast: entry ] ]. - morphToStep := entry receiver. - morphToStep world == aWorld ifFalse:[ - deletions ifNil: [deletions := OrderedCollection new]. - deletions addLast: entry]]. deletions ifNotNil:[ deletions do: [:entry| self stopStepping: entry receiver]]. self lockAlarmsDuring: [:locked | + locked alarmsDoSafely: [ :entry | + | morphToStep | - locked copy do: [:entry | morphToStep := entry receiver. + (morphToStep isMorph and: [morphToStep world == aWorld]) ifFalse: [ + locked removeAlarmWithReceiver: entry receiver selector: entry selector ] ] ]! - (morphToStep isMorph and:[morphToStep world == aWorld]) - ifFalse:[self removeAlarm: entry selector for: entry receiver]] - ].! Item was changed: ----- Method: WorldState>>removeAlarm:for: (in category 'alarms') ----- removeAlarm: aSelector for: aTarget "Remove the alarm with the given selector" self lockAlarmsDuring: [:locked | + locked removeAlarmWithReceiver: aTarget selector: aSelector ]! - | alarm | - alarm := locked - detect: [:any | any receiver == aTarget and: [any selector == aSelector]] - ifNone: [nil]. - alarm ifNotNil: [locked remove: alarm] - ]. - ! Item was changed: ----- Method: WorldState>>triggerAlarmsBefore: (in category 'alarms') ----- triggerAlarmsBefore: nowTime "Trigger all pending alarms that are to be executed before nowTime." | triggered | lastAlarmTime ifNil:[lastAlarmTime := nowTime]. (nowTime < lastAlarmTime or:[nowTime - lastAlarmTime > 10000]) ifTrue:[self adjustAlarmTimes: nowTime]. + triggered := self lockAlarmsDuring: [:pending | + pending removeAllAlarmsBefore: nowTime ]. - triggered := OrderedCollection new. - self lockAlarmsDuring: [:pending | - [pending isEmpty not and: [pending first scheduledTime < nowTime]] - whileTrue: [triggered add: pending removeFirst]]. triggered do: [:alarm | alarm value: nowTime]. lastAlarmTime := nowTime.! |
Free forum by Nabble | Edit this page |