Hi Ben,

On Wed, Feb 24, 2016 at 10:44 PM, Ben Coman <btc@openinworld.com> wrote:
On Thu, Feb 25, 2016 at 3:06 AM, Eliot Miranda <eliot.miranda@gmail.com> wrote:
>
>
> On Wed, Feb 24, 2016 at 7:23 AM, Ben Coman <btc@openinworld.com> wrote:
>>
>> Just sharing a passing thought so I don't forget it before I have time
>> to think more deeply on it.
>>
>> Several parts of Pharo (like SHTextStyler) are designed to have a
>> background process running, and when new input arrives that process is
>> killed so another can be immediately started - and sometimes we seem
>> to end up with large amounts of zombie processes.
>>
>> As I poke around Process>>terminate, I wonder if a different approach
>> would be to have a Process>>restart.�� I see there is Context>>restart.
>>
>> The starting the background process might look like...
>>
>>�� �� ��stylingProcess := [ [ "do stuff with nextData". self suspend ]
>> repeat ] forkAt: 30.
>>
>> and the code in the main morphic priority 40 thread might look like...
>>
>>�� �� sylingProcess suspend.
>>�� �� nextData := 'blah'.
>>�� �� sylingProcess restart.
>
>
> Hi Ben, so I'm assuming restart differs from resume.�� Am I right in thinking
> it cuts back the process to the "start"?�� Is the start the block from which
> the process was spawned, the argument to fork or forkAt:?

Thats right.�� Essentially like Exception>>retry, to do something like this...

�� �� restart := false.
�� �� workAvailable := Semaphore new.
�� �� process :=
�� �� [�� ��[�� Transcript crShow: 'At the start'.
�� �� �� �� �� �� work := 0.
�� �� �� �� �� �� [�� ��work := work + 1.
�� �� �� �� �� �� �� �� Transcript crShow: 'working on ' , work printString.
�� �� �� �� �� �� �� �� 1 second wait.
�� �� �� �� �� �� �� �� work>8 ifTrue:
�� �� �� �� �� �� �� �� [�� ��[Transcript crShow: 'Work complete.'] fork.
�� �� �� �� �� �� �� �� �� �� workAvailable wait.
�� �� �� �� �� �� �� �� �� �� restart := true.
�� �� �� �� �� �� �� �� ].
�� �� �� �� �� �� �� �� restart ifTrue: [self error].
�� �� �� �� �� �� �� �� work
�� �� �� �� �� �� ] repeat.
�� �� �� �� ] on: Error do: [:err| restart := false. err retry].
�� �� ] newProcess name:'My Restartable Worker'.
�� �� process resume.

�� �� "later do..."
�� �� restart := true.
�� �� "or after work complete..."
�� �� workAvailable signal.

�� �� "later still do..."
�� �� process terminate

...except being able to interrupt the process anytime,
i.e. not needing to wait to get to "restart ifTrue: [self error]."

It can be built simply above signalException:.�� So...

Process class methods for instance creation
forBlock: aBlockClosure priority: anInteger��
"Answer an instance of me that has suspended aContext at priority anInteger."

<primitive: 19> "Simulation guard"
| newProcess |
(newProcess := self new)
suspendedContext:
[[[newProcess result: aBlockClosure value.
�� false]
on: ProcessRestart
do: [:ex| true]]
whileTrue.
"Since control is now at the bottom there is no need to terminate (which
runs unwinds) since all unwinds have been run.�� Simply suspend.
Note that we must use this form rather than e.g. Processor suspendActive
so that isTerminated answers true. ��isTerminated requires that if there is a
suspended context it is the bottom-most, but using a send would result in
the process's suspendedContext /not/ being the bottom-most."
newProcess suspend] asContext;
priority: anInteger.
^newProcess
��
Process methods for process state change
restart
self signalException: ProcessRestart


btw, The requirement for the fork in "[Transcript crShow: 'Work
complete.'] fork"
is strange. Without it the semaphore does not wait, which seems a bug.

Is there a missing yield somewhere?
��

btw2, I needed to hack OCUndeclaredVariableWarning>>defaultAction to
stop the transcript being polluted by unknown playground variables. No
warranty on whether this is suitable to be permanent...
�� �� className = 'UndefinedObject' ifFalse: [
�� �� �� �� ��self methodNode selector ifNotNil: [self crTrace: className,
'>>', selector, ' ']
�� �� �� �� ��ifNil: [self traceCr:''].
�� �� �� �� ��self traceCr: '(' , varName , ' is Undeclared1) '.
�� �� ��].




On Thu, Feb 25, 2016 at 2:56 AM, Max Leske <maxleske@gmail.com> wrote:
> Fast spawning processes are very hard to debug (e.g. in the process browser).

This is exactly the use case I was thinking of.�� Often they've been
and gone before you even know they are there.�� Having a permanent
process aids discoverability of system background functionality.

cheers -ben




--
_,,,^..^,,,_
best,��Eliot