Joshua Gargus uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-jcg.301.mcz ==================== Summary ==================== Name: Morphic-jcg.301 Author: jcg Time: 9 January 2010, 2:31:01 am UUID: a3b88bbd-d51d-4318-9723-2724fa60d8ba Ancestors: Morphic-ar.300 Following Bert's suggestion in the "Future Sends" thread, use MorphicAlarms instead of forking a Process that immediately waits on a delay before scheduling them with the other deferred messages. This is Morphic-only behavior (implemented in MorphicProject), since other types of Projects don't have the MorphicAlarm mechanism available to them. (ignore Morphic-jcg.280, which is the same changes, but applied agains Morphic-dtl.279). =============== Diff against Morphic-ar.300 =============== Item was added: + ----- Method: MorphicAlarm>>sequenceNumber (in category 'accessing') ----- + sequenceNumber + "Answer the sequence number of the alarm, which is used to preserve ordering for alarms scheduled for the same time." + ^sequenceNumber ifNil: [0]! Item was added: + ----- Method: MorphicProject>>future:send:at:args: (in category 'futures') ----- + future: receiver send: aSelector at: deltaMSecs args: args + "Send a message deltaSeconds into the future. Answers a Promise that will be resolved at some time in the future." + | pr closure | + pr := Promise new. + closure := [pr resolveWith: (receiver perform: aSelector withArguments: args)]. + deltaMSecs = 0 + ifTrue: [self addDeferredUIMessage: closure] + ifFalse: [ + world + addAlarm: #addDeferredUIMessage: + withArguments: {closure} + for: self + at: (Time millisecondClockValue + deltaMSecs) + ]. + ^pr + ! Item was added: + ----- Method: MorphicAlarmQueue>>initialize (in category 'initialize') ----- + initialize + super initialize. + sequenceNumber := 0.! Item was added: + ----- 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 added: + ----- Method: MorphicAlarmQueue class>>convertAllAlarms (in category 'class initialization') ----- + convertAllAlarms + "Alarms should be kept in a MorphicAlarmQueue, not a Heap." + WorldState allSubInstancesDo: [:ws | ws convertAlarms]! Item was added: + ----- Method: MorphicProject>>future:do:at:args: (in category 'futures') ----- + future: receiver do: aSelector at: deltaMSecs args: args + "Send a message deltaSeconds into the future. No response is expected." + | msg | + msg := MessageSend receiver: receiver selector: aSelector arguments: args. + deltaMSecs = 0 + ifTrue: [self addDeferredUIMessage: msg] + ifFalse: [ + world + addAlarm: #addDeferredUIMessage: + withArguments: {msg} + for: self + at: (Time millisecondClockValue + deltaMSecs) + ].. + ^nil! Item was added: + Heap subclass: #MorphicAlarmQueue + instanceVariableNames: 'sequenceNumber' + classVariableNames: '' + poolDictionaries: '' + category: 'Morphic-Events'! + + !MorphicAlarmQueue commentStamp: '<historical>' 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 added: + ----- Method: MorphicAlarmQueue class>>initialize (in category 'class initialization') ----- + initialize + self convertAllAlarms.! Item was changed: ----- Method: WorldState>>convertAlarms (in category 'object fileIn') ----- convertAlarms + "We now store the alarms in a MorphicAlarmQueue, rather than a Heap." + alarms ifNotNil: [ + alarms class == MorphicAlarmQueue ifFalse: [ + | oldAlarms | + oldAlarms := alarms. + alarms := MorphicAlarmQueue new. + oldAlarms do: [:alarm | alarms add: alarm] + ] + ].! - - alarms ifNotNil: [alarms sortBlock: self alarmSortBlock]. "ensure cleaner block" - - ! Item was changed: MessageSend subclass: #MorphicAlarm + instanceVariableNames: 'scheduledTime sequenceNumber numArgs' - instanceVariableNames: 'scheduledTime numArgs' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Events'! Item was added: Item was added: + ----- 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 added: + ----- Method: MorphicAlarmQueue>>add: (in category 'adding') ----- + 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!!!!!!']. + ]! Item was changed: ----- Method: WorldState>>alarms (in category 'alarms') ----- alarms + ^alarms ifNil: [alarms := MorphicAlarmQueue new]! - ^alarms ifNil: [alarms := Heap sortBlock: self alarmSortBlock]! Item was added: Item was added: + ----- Method: MorphicAlarm>>sequenceNumber: (in category 'accessing') ----- + sequenceNumber: positiveInteger + "Set the sequence number of the alarm, which is used to preserve ordering for alarms scheduled for the same time." + sequenceNumber := positiveInteger! Item was added: |
Free forum by Nabble | Edit this page |