[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