Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!think.com!sdd.hp.com!hplabs!otter.hpl.hp.com!otter!rb From: rb@otter.hpl.hp.com (Richard Brown) Newsgroups: comp.lang.smalltalk Subject: Re: Time Slicing Message-ID: <2610009@otter.hpl.hp.com> Date: 23 May 91 07:24:27 GMT References: <2610008@otter.hpl.hp.com> Organization: Hewlett-Packard Laboratories, Bristol, UK. Lines: 95 Well I have had no response to this question so far, but this is the solution that I have implemented. I am still having a few problems with it. It seems that when the time slicer is running (-ie when I an running a back ground task but still want the user interface to run), if I then start another activity using fork, the user interface occasionally locks up. The background tasks continue to run to completion and attempt to display their results, but the ScheduledWindow which is popped up remains blank. It is not until I type ^C that all returns to normal. It seems that something was waiting on a Semaphore. The problem seems to be minimised if I fork at user background priority always. If I fork at userScheduling priority, then the problem occurs more often. I know this explanation is probably not too clear but it is quite complicated. If anyone has a better and more resilient time slicing mechanism, I would love to hear about it. Perhaps put your solution on this note. (This is for Smalltalk Rel4 running on an HP9000/375 work station). ------------------------------------------------------------------------------ Object subclass: #TimeSlicer instanceVariableNames: 'evaluationBlocks timeSlicerProcess timeSlicerEnabled uiDelay processDelay ' classVariableNames: '' poolDictionaries: '' category: 'Time Slicing'! !TimeSlicer methodsFor: 'time slicing'! disableTimeSlicing ^timeSlicerEnabled := false.! enableTimeSlicing ^timeSlicerEnabled := true.! startTimeSlicer "Continue to time slice whilst we have blocks to evaluate. Time slicing is achieved by stopping the user interface for periods of time (uiDelay) and then allowing it to run again for a period of time (processDelay). The reason we have implemented a time slicer because it is possible to lock out low priority processes simply by continually moving the mouse. This mechanism guarantees the user process a proportion of the cpu time." timeSlicerProcess notNil ifTrue: [^nil]. timeSlicerProcess := [ [(evaluationBlocks isEmpty not) & timeSlicerEnabled] whileTrue: [ evaluationBlocks do: [:block | block notNil ifTrue: [ block value ifFalse: [evaluationBlocks remove: block] ifTrue: [ | ioProcess | ioProcess := ScheduledControllers activeControllerProcess. ioProcess suspend. Cursor execute show. uiDelay wait. ioProcess resume. Cursor normal show. processDelay wait.]]]]. timeSlicerProcess := nil] forkAt: (Processor userInterruptPriority).! timeSliceWhile: aBlock evaluationBlocks add: aBlock. self startTimeSlicer.! ! !TimeSlicer methodsFor: 'accessing'! timeSlicerEnabled ^timeSlicerEnabled.! timeSlicerEnabled: aBoolean ^timeSlicerEnabled := aBoolean.! ! !TimeSlicer methodsFor: 'initialization'! initialize evaluationBlocks := OrderedCollection new. timeSlicerProcess := nil. timeSlicerEnabled := true. uiDelay := Delay forMilliseconds: 200. processDelay := Delay forMilliseconds: 200.! !