[Pkg] The Trunk: Morphic-jcg.302.mcz
commits at source.squeak.org
commits at source.squeak.org
Sat Jan 9 23:05:09 UTC 2010
Joshua Gargus uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-jcg.302.mcz
==================== Summary ====================
Name: Morphic-jcg.302
Author: jcg
Time: 9 January 2010, 3:04:38 am
UUID: 93a25230-2da7-463c-b82c-cdd8fee1b12d
Ancestors: Morphic-jcg.301
After version 301, sending #future from a non-UI thread is no longer thread-safe, because accesses to the MorphicAlarmQueue were not synchronized. Now they are, for all uses of Morphic alarms (i.e. even non-future-send users can now safely use Morphic alarms from other threads).
=============== Diff against Morphic-jcg.301 ===============
Item was changed:
----- Method: WorldState>>addAlarm:withArguments:for:at: (in category 'alarms') -----
addAlarm: aSelector withArguments: argArray for: aTarget at: scheduledTime
"Add a new alarm with the given set of parameters"
+ self lockAlarmsDuring: [:locked |
+ locked add: (MorphicAlarm
+ scheduledAt: scheduledTime
+ receiver: aTarget
+ selector: aSelector
+ arguments: argArray).
+ ]!
- self alarms add:
- (MorphicAlarm
- scheduledAt: scheduledTime
- receiver: aTarget
- selector: aSelector
- arguments: argArray).!
Item was changed:
----- Method: WorldState>>triggerAlarmsBefore: (in category 'alarms') -----
triggerAlarmsBefore: nowTime
"Trigger all pending alarms that are to be executed before nowTime."
- | pending |
lastAlarmTime ifNil:[lastAlarmTime := nowTime].
(nowTime < lastAlarmTime or:[nowTime - lastAlarmTime > 10000])
ifTrue:[self adjustAlarmTimes: nowTime].
+ self lockAlarmsDuring: [:pending |
+ [pending isEmpty not and:[pending first scheduledTime < nowTime]]
+ whileTrue:[pending removeFirst value: nowTime].
+ ].
- pending := self alarms.
- [pending isEmpty not and:[pending first scheduledTime < nowTime]]
- whileTrue:[pending removeFirst value: nowTime].
lastAlarmTime := nowTime.!
Item was changed:
Heap subclass: #MorphicAlarmQueue
+ instanceVariableNames: 'mutex sequenceNumber'
- instanceVariableNames: 'sequenceNumber'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Events'!
+ !MorphicAlarmQueue commentStamp: 'jcg 1/9/2010 13:34' prior: 0!
- !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 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.
+ self lockAlarmsDuring: [:locked |
+ locked do:[:alarm| alarm scheduledTime: alarm scheduledTime + deltaTime].
+ ]!
- self alarms do:[:alarm| alarm scheduledTime: alarm scheduledTime + deltaTime].!
Item was added:
+ ----- Method: WorldState>>lockAlarmsDuring: (in category 'alarms') -----
+ lockAlarmsDuring: actionBlock
+ "All accesses to the alarms queue is synchronized by a mutex. Answer the result of evaluating the 1-argument 'actionBlock'."
+ alarms ifNil: [alarms := MorphicAlarmQueue new].
+ ^alarms mutex critical: [
+ actionBlock value: alarms
+ ]!
Item was added:
+ ----- Method: MorphicAlarmQueue>>mutex (in category 'accessing') -----
+ mutex
+ ^mutex ifNil: [mutex := Mutex new]!
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 morphToStep |
deletions := nil.
stepList do: [: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 copy do: [:entry |
+ morphToStep := entry receiver.
+ (morphToStep isMorph and:[morphToStep world == aWorld])
+ ifFalse:[self removeAlarm: entry selector for: entry receiver]]
+ ].!
- self alarms copy do:[:entry|
- morphToStep := entry receiver.
- (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 |
+ | alarm |
+ alarm := locked
+ detect: [:any | any receiver == aTarget and: [any selector == aSelector]]
+ ifNone: [nil].
+ alarm ifNotNil: [locked remove: alarm]
+ ].
+ !
-
- | alarm |
- alarm := self alarms
- detect: [:any | any receiver == aTarget and: [any selector == aSelector]]
- ifNone: [nil].
- alarm isNil ifFalse: [self alarms remove: alarm]!
Item was removed:
- ----- Method: WorldState>>alarmSortBlock (in category 'alarms') -----
- alarmSortBlock
- ^[ :alarm1 :alarm2 |
- alarm1 scheduledTime < alarm2 scheduledTime.
- ]!
More information about the Packages
mailing list