Terminating a Process when an object dies

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
23 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Terminating a Process when an object dies

Sean P. DeNigris
Administrator
If my object is using a process internally that should run only as long as the object is around, how do I do that? I searched the ml's for "Finalization", but couldn't quite make sense of the process.

Thanks!
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Camillo Bruni-3

On 2013-04-23, at 05:17, "Sean P. DeNigris" <[hidden email]> wrote:

> If my object is using a process internally that should run only as long as
> the object is around, how do I do that? I searched the ml's for
> "Finalization", but couldn't quite make sense of the process.

If your process refers to this Object (e.g. methods of said Object are
evaluated in a this thread) the thing you want to do is not possible.

Processes are root objects for the GarbageCollector hence all the objects
in its execution stack won't get garbage collected.

Otherwise check WeakRegistry

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Igor Stasenko
In reply to this post by Sean P. DeNigris
On 23 April 2013 05:16, Sean P. DeNigris <[hidden email]> wrote:
> If my object is using a process internally that should run only as long as
> the object is around, how do I do that? I searched the ml's for
> "Finalization", but couldn't quite make sense of the process.
>

you don't need finalization.. just a weak reference. something like this:

array := WeakArray with: myObject.

[[ array first notNil] whileTrue: [ ...... ]] fork.

> Thanks!
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
Igor Stasenko wrote
you don't need finalization.. just a weak reference. something like this:

array := WeakArray with: myObject.

[[ array first notNil] whileTrue: [ ...... ]] fork.
Timer>>start

        | array |
        array := WeakArray with: self.
        process := [
                [ array first notNil ] whileTrue: [
                        interval asDelay wait.
                        self value: self value + 1.
                        self announcer announce: (TimerValueChanged to: self value) ] ] fork.

Timer new start.
Smalltalk garbageCollect.

The process is still there...
I'm attaching (to Nabble) a screenshot of #pointersTo
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sven Van Caekenberghe-2
I think it is as Camillo said:

the Timer object holds the Process object
the block in the Process holds the Timer object in its closure.
the Process is held by the system

=> neither can become garbage

Maybe Igor meant to not put the process in an instance variable…

But I fear that won't do: the block closure keeps on referring to self, which is your timer.

On 23 Apr 2013, at 14:17, "Sean P. DeNigris" <[hidden email]> wrote:

> Igor Stasenko wrote
>> you don't need finalization.. just a weak reference. something like this:
>>
>> array := WeakArray with: myObject.
>>
>> [[ array first notNil] whileTrue: [ ...... ]] fork.
>
> Timer>>start
>
> | array |
> array := WeakArray with: self.
> process := [
> [ array first notNil ] whileTrue: [
> interval asDelay wait.
> self value: self value + 1.
> self announcer announce: (TimerValueChanged to: self value) ] ] fork.
>
> Timer new start.
> Smalltalk garbageCollect.
>
> The process is still there...
> I'm attaching (to Nabble) a screenshot of #pointersTo
> <http://forum.world.st/file/n4683095/Screen_Shot_2013-04-23_at_8.16.01_AM.png>
>
>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683095.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>


Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Igor Stasenko
In reply to this post by Sean P. DeNigris
On 23 April 2013 14:17, Sean P. DeNigris <[hidden email]> wrote:

> Igor Stasenko wrote
>> you don't need finalization.. just a weak reference. something like this:
>>
>> array := WeakArray with: myObject.
>>
>> [[ array first notNil] whileTrue: [ ...... ]] fork.
>
> Timer>>start
>
>         | array |
>         array := WeakArray with: self.
>         process := [
>                 [ array first notNil ] whileTrue: [
>                         interval asDelay wait.
>                         self value: self value + 1.
>                         self announcer announce: (TimerValueChanged to: self value) ] ] fork.
>
> Timer new start.
> Smalltalk garbageCollect.
>
> The process is still there...

but what you expecting?
you refer to 'self' multiple times. sure thing it cannot be GC-ed,
neither process will die because
of plenty of references on stack.
Even block closure which you creating for fork will have home context
which keeps reference to 'self',
e.g. receiver.


> I'm attaching (to Nabble) a screenshot of #pointersTo
> <http://forum.world.st/file/n4683095/Screen_Shot_2013-04-23_at_8.16.01_AM.png>
>
>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683095.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Luc Fabresse
Hi Sean,

  We experienced that also with Noury and Jannik.
 The trick has been to extract the block in a class side method.
 Example: 

 Timer>>start
    process := self class createProcessFor: self

 Timer class>>createProcessFor: aTimer
  ^[ aTimer value: aTimer value + 1.......] fork


 Now:

 t := Timer new start. 
 t := nil

 makes the process dispear as well.
 ok not really beautiful but it works ;-)

Cheers,

Luc




#Luc


2013/4/23 Igor Stasenko <[hidden email]>
On 23 April 2013 14:17, Sean P. DeNigris <[hidden email]> wrote:
> Igor Stasenko wrote
>> you don't need finalization.. just a weak reference. something like this:
>>
>> array := WeakArray with: myObject.
>>
>> [[ array first notNil] whileTrue: [ ...... ]] fork.
>
> Timer>>start
>
>         | array |
>         array := WeakArray with: self.
>         process := [
>                 [ array first notNil ] whileTrue: [
>                         interval asDelay wait.
>                         self value: self value + 1.
>                         self announcer announce: (TimerValueChanged to: self value) ] ] fork.
>
> Timer new start.
> Smalltalk garbageCollect.
>
> The process is still there...

but what you expecting?
you refer to 'self' multiple times. sure thing it cannot be GC-ed,
neither process will die because
of plenty of references on stack.
Even block closure which you creating for fork will have home context
which keeps reference to 'self',
e.g. receiver.


> I'm attaching (to Nabble) a screenshot of #pointersTo
> <http://forum.world.st/file/n4683095/Screen_Shot_2013-04-23_at_8.16.01_AM.png>
>
>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683095.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.


Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sven Van Caekenberghe-2
Hi Luc, Sean, Igor,

I still don't think that is right (although I did not actually try to run your approach): you still make the block closure of the process refer strongly to the timer object.

I tried it as follows (.st file included at the end):

Object subclass: #TestTimer
        instanceVariableNames: 'counter interval'

TestTimer>>#initialize
        interval := 5 seconds asDelay.
        counter := 0.
        self class start: (WeakArray with: self)

TestTimer>>#tick
        interval wait.
        counter := counter + 1

TestTimer class>>#start: reference
        [
                [ reference first isNil ] whileFalse: [
                        reference first tick ] ]
                forkAt: Processor userBackgroundPriority
                named: 'Test Timer'

Sadly it still does not work, and I don't know why ;-)

        TestTimer new.

        3 timesRepeat: [ Smalltalk garbageCollect ].

        TestTimer allInstances

You can see the timer count going up every 5 seconds when inspecting the instance, but you have to close the inspector otherwise that is another reference. Exploring strong pointers lists the WeakArray instance...

Sven




On 23 Apr 2013, at 16:01, Luc Fabresse <[hidden email]> wrote:

> Hi Sean,
>
>   We experienced that also with Noury and Jannik.
>  The trick has been to extract the block in a class side method.
>  Example:
>
>  Timer>>start
>     process := self class createProcessFor: self
>
>  Timer class>>createProcessFor: aTimer
>   ^[ aTimer value: aTimer value + 1.......] fork
>
>
>  Now:
>
>  t := Timer new start.
>  t := nil
>
>  makes the process dispear as well.
>  ok not really beautiful but it works ;-)
>
> Cheers,
>
> Luc
>
>
>
>
> #Luc
>
>
> 2013/4/23 Igor Stasenko <[hidden email]>
> On 23 April 2013 14:17, Sean P. DeNigris <[hidden email]> wrote:
> > Igor Stasenko wrote
> >> you don't need finalization.. just a weak reference. something like this:
> >>
> >> array := WeakArray with: myObject.
> >>
> >> [[ array first notNil] whileTrue: [ ...... ]] fork.
> >
> > Timer>>start
> >
> >         | array |
> >         array := WeakArray with: self.
> >         process := [
> >                 [ array first notNil ] whileTrue: [
> >                         interval asDelay wait.
> >                         self value: self value + 1.
> >                         self announcer announce: (TimerValueChanged to: self value) ] ] fork.
> >
> > Timer new start.
> > Smalltalk garbageCollect.
> >
> > The process is still there...
>
> but what you expecting?
> you refer to 'self' multiple times. sure thing it cannot be GC-ed,
> neither process will die because
> of plenty of references on stack.
> Even block closure which you creating for fork will have home context
> which keeps reference to 'self',
> e.g. receiver.
>
>
> > I'm attaching (to Nabble) a screenshot of #pointersTo
> > <http://forum.world.st/file/n4683095/Screen_Shot_2013-04-23_at_8.16.01_AM.png>
> >
> >
> >
> > -----
> > Cheers,
> > Sean
> > --
> > View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683095.html
> > Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
> >
>
>
>
> --
> Best regards,
> Igor Stasenko.
>
>


TestTimer.st (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
In reply to this post by Igor Stasenko
Igor Stasenko wrote
but what you expecting?
you refer to 'self' multiple times. sure thing it cannot be GC-ed,
neither process will die because
of plenty of references on stack.
Even block closure which you creating for fork will have home context
which keeps reference to 'self',
e.g. receiver.
I'm expecting magic apparently because I am stupid when it comes to processes ;) I changed all the "self"s to array first, which also didn't work, but then I read your statement about the home context...

Luc's class-side trick seems to work:
Timer>>start

        | array |
        array := WeakArray with: self.
        process := self class createProcessFor: array. "tried passing self here, but it seemed to keep the process around"

Timer class>>createProcessFor: aWeakArray

        [ [ aWeakArray first notNil ] whileTrue: [
                | timer |
                aWeakArray first interval asDelay wait.
                "We have to check again if the timer was garbage collected during the wait"
                aWeakArray first ifNotNil: [
                        aWeakArray first value: aWeakArray first value + 1.
                        aWeakArray first announcer announce: (TimerValueChanged to: aWeakArray first value) ] ] ] fork.

Wow, it would seem that an object using a process internally that is only valid when the object is around is a fairly common use case. I can't believe how complicated this is :/
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sven Van Caekenberghe-2
Sean,

On 23 Apr 2013, at 18:02, "Sean P. DeNigris" <[hidden email]> wrote:

> Luc's class-side trick seems to work:
> Timer>>start
>
> | array |
> array := WeakArray with: self.
> process := self class createProcessFor: array. "tried passing self here,
> but it seemed to keep the process around"
>
> Timer class>>createProcessFor: aWeakArray
>
> [ [ aWeakArray first notNil ] whileTrue: [
> | timer |
> aWeakArray first interval asDelay wait.
> "We have to check again if the timer was garbage collected during the
> wait"
> aWeakArray first ifNotNil: [
> aWeakArray first value: aWeakArray first value + 1.
> aWeakArray first announcer announce: (TimerValueChanged to: aWeakArray
> first value) ] ] ] fork.
Are you sure it works ?
How do you test ?

In my code, I tried to do exactly what you are doing, except for the announcement, but I don't think it works.

I tried to formalize a test, but you probably have to use the #debug: on TestCase otherwise the test is run twice and fails on the first assert. It could well be that the test is bogus (does the finalization get a chance to run ?).

It only works if I terminate the process via the Process Browser.

Any ideas ?

These are old school file outs in _UnpackagedPackage:




Sven






TestTimer.st (1K) Download Attachment
TestTimerTests.st (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
> Are you sure it works ?
> How do you test ?
Pretty sure. I'm attaching the actual code and some tests. If you run TimerTest>>#testStart from Nautilus with an open Process Browser (with auto-update enabled), you'll see the process appear and then disappear.


MorphicExtrasSpd-Leds.st (6K) Download Attachment
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
Sean P. DeNigris wrote
If you run TimerTest>>#testStart from Nautilus with an open Process Browser (with auto-update enabled), you'll see the process appear and then disappear.
Although if I evaluate the snippet in the class comment of SpdLedMorph, the process hangs around. Arggghhhh. This is crazy!!!
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Igor Stasenko
In reply to this post by Sean P. DeNigris
On 23 April 2013 18:02, Sean P. DeNigris <[hidden email]> wrote:

> Igor Stasenko wrote
>> but what you expecting?
>> you refer to 'self' multiple times. sure thing it cannot be GC-ed,
>> neither process will die because
>> of plenty of references on stack.
>> Even block closure which you creating for fork will have home context
>> which keeps reference to 'self',
>> e.g. receiver.
>
> I'm expecting magic apparently because I am stupid when it comes to
> processes ;) I changed all the "self"s to array first, which also didn't
> work, but then I read your statement about the home context...
>
> Luc's class-side trick seems to work:
> Timer>>start
>
>         | array |
>         array := WeakArray with: self.
>         process := self class createProcessFor: array. "tried passing self here,
> but it seemed to keep the process around"
>
of course, because the home context (will be the method below) of
closure captures method's arguments,
and holding them strongly..

> Timer class>>createProcessFor: aWeakArray
>
>         [ [ aWeakArray first notNil ] whileTrue: [
>                 | timer |
>                 aWeakArray first interval asDelay wait.
>                 "We have to check again if the timer was garbage collected during the
> wait"
>                 aWeakArray first ifNotNil: [
>                         aWeakArray first value: aWeakArray first value + 1.
>                         aWeakArray first announcer announce: (TimerValueChanged to: aWeakArray
> first value) ] ] ] fork.
>
> Wow, it would seem that an object using a process internally that is only
> valid when the object is around is a fairly common use case. I can't believe
> how complicated this is :/
>
it is not apparent to me why this is common use case. :)

you can also simply pass a copy of 'self' to process.
as long as copy accessing same announcer, your ticker process will
work perfectly.
then all you would need to do is:

| copy |
copy := self copy.

process := self class createProcessFor: copy.
WeakRegistry default add: self executor: copy.

and implement:

finalize
  process terminate.
  process := nil.


Then createProcessFor: will be simple:

Timer class>>createProcessFor: timer
 [
[ timer wait. " make Demeter a bit happier"
  timer tick. "this should increment counter and announce TimerValueChanged,
                     like that we're not make Demeter unhappy"
] whileTrue   ] fork.

(actually , to make mr.Demeter completely happy, i would do
  [ timer waitAndTick ] whileTrue.
)

and, tick, will be something like that:

tick
  process ifNil: [ ^ false ].
  self incrementCounter.
  self announce: (MyGreatAnnouncement with: whatever).
  ^ true.

cheerz :)

> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683144.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Igor Stasenko
On 23 April 2013 20:32, Igor Stasenko <[hidden email]> wrote:

> On 23 April 2013 18:02, Sean P. DeNigris <[hidden email]> wrote:
>> Igor Stasenko wrote
>>> but what you expecting?
>>> you refer to 'self' multiple times. sure thing it cannot be GC-ed,
>>> neither process will die because
>>> of plenty of references on stack.
>>> Even block closure which you creating for fork will have home context
>>> which keeps reference to 'self',
>>> e.g. receiver.
>>
>> I'm expecting magic apparently because I am stupid when it comes to
>> processes ;) I changed all the "self"s to array first, which also didn't
>> work, but then I read your statement about the home context...
>>
>> Luc's class-side trick seems to work:
>> Timer>>start
>>
>>         | array |
>>         array := WeakArray with: self.
>>         process := self class createProcessFor: array. "tried passing self here,
>> but it seemed to keep the process around"
>>
> of course, because the home context (will be the method below) of
> closure captures method's arguments,
> and holding them strongly..
>
>> Timer class>>createProcessFor: aWeakArray
>>
>>         [ [ aWeakArray first notNil ] whileTrue: [
>>                 | timer |
>>                 aWeakArray first interval asDelay wait.
>>                 "We have to check again if the timer was garbage collected during the
>> wait"
>>                 aWeakArray first ifNotNil: [
>>                         aWeakArray first value: aWeakArray first value + 1.
>>                         aWeakArray first announcer announce: (TimerValueChanged to: aWeakArray
>> first value) ] ] ] fork.
>>
>> Wow, it would seem that an object using a process internally that is only
>> valid when the object is around is a fairly common use case. I can't believe
>> how complicated this is :/
>>
> it is not apparent to me why this is common use case. :)
>
> you can also simply pass a copy of 'self' to process.
> as long as copy accessing same announcer, your ticker process will
> work perfectly.
> then all you would need to do is:
>
> | copy |
> copy := self copy.
>
> process := self class createProcessFor: copy.
> WeakRegistry default add: self executor: copy.
>
> and implement:
>
> finalize
>   process terminate.
>   process := nil.

small correction.. while writing this, i first used #terminate,
but then added,  'process := nil' , which is enough,
because it letting the process exit from loop graciously and terminate
by itself.

>
> Then createProcessFor: will be simple:
>
> Timer class>>createProcessFor: timer
>  [
> [ timer wait. " make Demeter a bit happier"
>   timer tick. "this should increment counter and announce TimerValueChanged,
>                      like that we're not make Demeter unhappy"
> ] whileTrue   ] fork.
>
> (actually , to make mr.Demeter completely happy, i would do
>   [ timer waitAndTick ] whileTrue.
> )
>
> and, tick, will be something like that:
>
> tick
>   process ifNil: [ ^ false ].
>   self incrementCounter.
>   self announce: (MyGreatAnnouncement with: whatever).
>   ^ true.
>
> cheerz :)
>
>> -----
>> Cheers,
>> Sean
>> --
>> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683144.html
>> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko.



--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
In reply to this post by Igor Stasenko
Igor Stasenko wrote
it is not apparent to me why this is common use case. :)
In the sense that Smalltalk is prototype Dynabook software, part of the purpose of which is to do simulations ;) Also, I've seen this come up quite a bit and usually the suggestion is to hijack Morphic stepping, which seems to me like too ugly a hack.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Luc Fabresse
In reply to this post by Igor Stasenko
Hi all,


@Sven, yes of course I forgot the WeakArray to save the hard ref in my previous explanation.
 

2013/4/23 Igor Stasenko <[hidden email]>
On 23 April 2013 18:02, Sean P. DeNigris <[hidden email]> wrote:
> Igor Stasenko wrote
>> but what you expecting?
>> you refer to 'self' multiple times. sure thing it cannot be GC-ed,
>> neither process will die because
>> of plenty of references on stack.
>> Even block closure which you creating for fork will have home context
>> which keeps reference to 'self',
>> e.g. receiver.
>
> I'm expecting magic apparently because I am stupid when it comes to
> processes ;) I changed all the "self"s to array first, which also didn't
> work, but then I read your statement about the home context...
>
> Luc's class-side trick seems to work:
> Timer>>start
>
>         | array |
>         array := WeakArray with: self.
>         process := self class createProcessFor: array. "tried passing self here,
> but it seemed to keep the process around"
>
of course, because the home context (will be the method below) of
closure captures method's arguments,
and holding them strongly.. 

> Timer class>>createProcessFor: aWeakArray
>
>         [ [ aWeakArray first notNil ] whileTrue: [
>                 | timer |
>                 aWeakArray first interval asDelay wait.
>                 "We have to check again if the timer was garbage collected during the
> wait"
>                 aWeakArray first ifNotNil: [
>                         aWeakArray first value: aWeakArray first value + 1.
>                         aWeakArray first announcer announce: (TimerValueChanged to: aWeakArray
> first value) ] ] ] fork.
>
> Wow, it would seem that an object using a process internally that is only
> valid when the object is around is a fairly common use case. I can't believe
> how complicated this is :/
>
it is not apparent to me why this is common use case. :)

you can also simply pass a copy of 'self' to process.
as long as copy accessing same announcer, your ticker process will
work perfectly.
then all you would need to do is:

| copy |
copy := self copy.

@Igor.
It will not work here I think.
because you make the shallow copy before initializing the process and the finalize message is then sent to the copy.
as Sven proposed, a WeakArray would be good but I never deeply test it.

Anyway, I always fight with the finalization mechanism.

With Noury we wrote an ActiveObject class some time ago that has an internal process that is stopped and the activeobject is finalized.
The only thing is to be **really** carreful when giving the block to the ActiveObject to not introduce references.

Here one of the test case that is green:

testDoesStopBlockUponFinalizationForLowestPriority
|counter startSemaphore finalizationSemaphore process |
counter := 0.
startSemaphore := Semaphore new.
finalizationSemaphore := Semaphore new.
activeObject := ActiveObject 
do: [
startSemaphore signal.
[(Delay forMilliseconds: 50) wait]repeat
]
ensure: [
counter := 1.
finalizationSemaphore signal.
].
activeObject 
priority: Processor lowestPriority;
start.
self deny: (startSemaphore waitTimeoutSeconds: 2).
process := activeObject process.
activeObject := nil.
Smalltalk garbageCollect.
self deny: (finalizationSemaphore waitTimeoutSeconds: 2).
self assert: counter = 1.
self assert: process isTerminated 


Here the whole code:

MCHttpRepository
user: ''
password: ''

Luc



process := self class createProcessFor: copy.
WeakRegistry default add: self executor: copy.

and implement:

finalize
  process terminate.
  process := nil.


Then createProcessFor: will be simple:

Timer class>>createProcessFor: timer
 [
[ timer wait. " make Demeter a bit happier"
  timer tick. "this should increment counter and announce TimerValueChanged,
                     like that we're not make Demeter unhappy"
] whileTrue   ] fork.

(actually , to make mr.Demeter completely happy, i would do
  [ timer waitAndTick ] whileTrue.
)

and, tick, will be something like that:

tick
  process ifNil: [ ^ false ].
  self incrementCounter.
  self announce: (MyGreatAnnouncement with: whatever).
  ^ true.

cheerz :)

> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683144.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.


Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
Luc Fabresse wrote
@Igor.
It will not work here I think.
because you make the shallow copy before initializing the process and the
finalize message is then sent to the copy.
Yes, I had to copy the process variable to the copy, but it just gets uglier and uglier...
        copy := self copy.
        process := self class createProcessFor: copy.
        copy process: process.
        WeakRegistry default add: self executor: copy.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sven Van Caekenberghe-2
In reply to this post by Sean P. DeNigris

On 23 Apr 2013, at 19:59, "Sean P. DeNigris" <[hidden email]> wrote:

> Sean P. DeNigris wrote
>> If you run TimerTest>>#testStart from Nautilus with an open Process
>> Browser (with auto-update enabled), you'll see the process appear and then
>> disappear.
>
> Although if I evaluate the snippet in the class comment of SpdLedMorph, the
> process hangs around. Arggghhhh. This is crazy!!!

I loaded your code and I have the impression that it works, both in the test and in a workspace.
But it drives me crazy that my version does not seem to work.
I will have to come back to this tomorrow with a fresh mind.

Sven
Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Igor Stasenko
In reply to this post by Sean P. DeNigris
On 23 April 2013 21:47, Sean P. DeNigris <[hidden email]> wrote:

> Luc Fabresse wrote
>> @Igor.
>> It will not work here I think.
>> because you make the shallow copy before initializing the process and the
>> finalize message is then sent to the copy.
>
> Yes, I had to copy the process variable to the copy, but it just gets uglier
> and uglier...
>         copy := self copy.
>         process := self class createProcessFor: copy.
>         copy process: process.
>         WeakRegistry default add: self executor: copy.
>
well, #createProcessFor: implies that copy get's the pointer to process.
no need to pass it back to sender.

>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Terminating-a-Process-when-an-object-dies-tp4683036p4683183.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>



--
Best regards,
Igor Stasenko.

Reply | Threaded
Open this post in threaded view
|

Re: Terminating a Process when an object dies

Sean P. DeNigris
Administrator
Igor Stasenko wrote
well, #createProcessFor: implies that copy get's the pointer to process.
no need to pass it back to sender.
I need the return value because I need to suspend and resume the process from the original Timer, which is what the GUI holds a pointer to.
Cheers,
Sean
12