Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
September 2014
- 1227 messages
Re: [Pharo-dev] deployment components
by Craig Latta
Hi Torsten--
> The interesting part is not to add all kind of stuff to Smalltalk -
> the interesting part is what is the most minimalistic system to allow
> for something extensible and still flexible (even within the
> meta-system) so that one can bootstrap things on top.
Yes, that's my interest precisely.
-C
--
Craig Latta
netjam.org
+31 6 2757 7177 (SMS ok)
+ 1 415 287 3547 (no SMS)
Sept. 24, 2014
Re: [Pharo-dev] deployment components
by Craig Latta
Hi Frank--
I wrote:
> Right, there's no need for anyone to use UUIDs when referring to
> classes in Smalltalk expressions.
Torsten responded:
> Yes, exactly this. We still use regular names for the classes - but
> for the tools they have a distinguishable ID. Best is to use a UUID
> for the ID as it is unique from the beginning. So if you create a
> class "Foo" and I create one both are unqique by ID - even when using
> the same name.
You responded to Torsten:
> The problem I have with UUIDs is that...
Hooray! Discussion! :)
> ...in a distributed setting, you need to rely on everyone to generate
> UUIDs correctly. Now IF everyone implements UUID generation
> correctly...
This is not hard, if there are common implementations at the
Smalltalk level (like we have common collection classes), or at the
virtual machine level (like we have common plugins).
> ...and IF everyone plays the game in good faith...
Whoa, if you're going to invoke that concern, then I wonder how you
can tolerate what we've already been doing. Namely:
- Compiling source code with no way to trust its authorship.
- Compiling source code with no way to trust that the code does what
the authors say it does (trusting authorship would help somewhat).
- Compiling source code with no way to trust that the target
compilation environment is sufficiently like the one in which the
source code was developed.
> ...you will almost certainly not get a UUID clash. But when you say
> your code depends on package/class/object/method with guid SOME_GUID,
> and I as a bad actor inject my own class with guid SOME_GUID, how are
> you to know that you've just been 0wned?
Again, how would you know today that the filein or Monticello
package you just loaded has 0wned you? When would you know? What would
you do about it?
I think we have to concede that a motivated insider will always be
able to do bad things for a while before being caught, probably
involving social mechanisms. I'm interested in how to minimize this
time, and how to undo the bad things. With the Naiad module system, I
want to identify, as soon as possible, the human interactions required
to establish trust, and facilitate them.
Naiad modules are synchronized live between systems (without
recompiling source code; only authors compile source code). You could
know you're likely to be 0nwed if you proceed with a module
synchronization because the cryptographic signature of a module is
incorrect for its purported authors. It would be similar to knowing that
the PGP-signed message you just read isn't really from the person whose
key you verified earlier.
> Wouldn't it be better, instead of using a key-value store (key K maps
> to value V), we have a store that uses function_of(V) maps to value V?
> Like in git: a commit is uniquely identified by its hash and, because
> the hash is a checksum, you can't - short of engineering a SHA-1
> collision (good luck with that) - forge part of the system.
The things we want to identify have state that changes over time;
their hashes would also change over time. This is fine for things like a
module signature during a synchronization conversation (in fact, I'd
like to leverage the actual existing public-key cryptography
infrastructure for Naiad). It's inappropriate for referring to a
changing class over the course of years. UUIDs are a straightforward and
well-known way of generating IDs for things which change.
Anyway, there it is, both UUIDs and hashing are involved.
-C
--
Craig Latta
netjam.org
+31 6 2757 7177 (SMS ok)
+ 1 415 287 3547 (no SMS)
Sept. 24, 2014
Re: [Pharo-dev] deployment components
by Craig Latta
Hi--
> Actually, I am fine with the prefixes. Objective-C also works like
> that and well, it hasn't exactly hampered its community to scale.
I think Objective-C might have had one or two other forces behind
it to compensate. :)
> I have done my share of Java and yeah, sure, there are a lot of
> enterprise grade things in there. So many that actual development and
> delivery usually slows down to a crawl with lots of Java priests who
> confuse delivery of business value with technical show off.
For me this stuff isn't about being "enterprise-grade" or even
particularly sophisticated. It's rudimentary, like bothering to remember
where your car is parked. The lack of it is something that causes
potential participants I meet to stop listening, especially given the
power of the system in general. It's a strange discontinuity.
-C
--
Craig Latta
netjam.org
+31 6 2757 7177 (SMS ok)
+ 1 415 287 3547 (no SMS)
Sept. 24, 2014
Re: [Pharo-dev] Custom list/tree items in Spec
by Nicolai Hess
2014-09-24 10:42 GMT+02:00 Yuriy Tymchuk <yuriy.tymchuk(a)me.com>:
> Hi,
>
> if it possible to design custom item model for list or tree item in Spec?
> I know that there is an option to add icon and so on, but can I design my
> own model? For example make it a two line item with 2 radio buttonsâ¦
>
> Cheers
> Uko
>
You can do funny/ugly things in spec, don't know if this is supposed to
work that way, but it does.
(The magic lies in the displayBlock... buildWithSpec)
| nodeCreator ui layout |
"helper block for creating a dynamicmodel based on a FileReference item"
nodeCreator := [ :item |
| uii layouti |
uii := DynamicComposableModel new.
uii instantiateModels: #(#text LabelModel #button1 #CheckBoxModel
#button2 #CheckBoxModel).
layouti := SpecLayout composed
newColumn: [ :col |
col
add: #text;
newRow:[:row|
row
add: #button1;
add: #button2 ]
]
yourself.
uii button1 label: 'writeable'.
uii button2 label: 'readable'.
uii text text:item pathString.
uii button1 state: item isWritable.
uii button2 state: item isReadable.
uii button2 whenChangedDo:[: s | s inform:'me changed'].
uii layout:layouti.
uii ].
"this is the main widget "
ui := DynamicComposableModel new.
ui instantiateModels: #(#tree #TreeModel).
ui tree roots: {(FileLocator desktop)}.
ui tree
childrenBlock: [ :it |
it isDirectory
ifTrue: [ it children collect: [ :item | |icon|
icon := item isDirectory
ifTrue: [ Smalltalk ui icons smallOpenIcon ]
ifFalse: [ Smalltalk ui icons smallLeftFlushIcon ].
TreeNodeModel new
content: item;
icon: icon
.] ]
ifFalse: [ {} ] ].
ui tree
rootNodeHolder: [ :item |
| icon |
icon := item isDirectory
ifTrue: [ Smalltalk ui icons smallOpenIcon ]
ifFalse: [ Smalltalk ui icons smallLeftFlushIcon ].
TreeNodeModel new
content: item;
icon: icon ].
"dynamically build treenode*morph* by calling the spec interpreter with our
nodecreator block"
ui tree displayBlock: [ :item |self haltOnce. (nodeCreator value: item)
buildWithSpec].
layout := SpecLayout composed
newColumn: [ :c | c add: #tree ];
yourself.
^ ui openWithSpecLayout: layout
Sept. 24, 2014
Re: [Pharo-dev] [Vm-dev] re: deployment components (was "The Dilemma: Building a Futuristic GUI for Ephestos")
by Frank Shearar
On 24 September 2014 09:16, Torsten Bergmann <astares(a)gmx.de> wrote:
>
> Craig Latta wrote:
>>Right, there's no need for anyone to use UUIDs when referring to
>>classes in Smalltalk expressions.
>
> Yes, exactly this. We still use regular names for the classes - but for the tools
> they have a distinguishable ID.
> Best is to use a UUID for the ID as it is unique from the beginning. So if you
> create a class "Foo" and I create one both are unqique by ID - even when using
> the same name.
The problem I have with UUIDs is that, in a distributed setting, you
need to rely on everyone to generate UUIDs correctly. Now IF everyone
implements UUID generation correctly, and IF everyone plays the game
in good faith, you will almost certainly not get a UUID clash. But
when you say your code depends on package/class/object/method with
guid SOME_GUID, and I as a bad actor inject my own class with guid
SOME_GUID, how are you to know that you've just been 0wned?
Wouldn't it be better, instead of using a key-value store (key K maps
to value V), we have a store that uses function_of(V) maps to value V?
Like in git: a commit is uniquely identified by its hash and, because
the hash is a checksum, you can't - short of engineering a SHA-1
collision (good luck with that) - forge part of the system.
> The "rest" is implemeting tooling support. When you write "Foo" in a workspace
> then the workspace either already has a naming context to resolve the name (see [1]
> or could provide you with a selection if there is more than one. Internally you could
> bind to the right class by using the ID.
Yes, that "rest" is most of the work. But you know this because of the
scare quotes :)
> I hate prefixing the classes as we now do, I want to name the classes "Instruction"
> not "IRInstruction" in Opal or "AJInstruction" in AsmJIT, especially since "IR" and "AJ"
> do not really tell you anything. Smalltalk names should be understandable. Additionally
> we should have meaningfull (and also unique) names also for namespaces.
>
> Also the current three/two letter prefixing of classes that is used in Squeak or Pharo
> only scales well for small communities...
>
> When there are things I like in Java then it is the fact to use reverse domains
> for namespaces. It is easy, understandable and I could also easily check if there
> is a web location.
>
> This way a namespace "org.apache.maven" gives you something meaningful, I can even
> visit http://maven.apache.org/. Allows the community to easily scale with thousands of
> classes without having clashes.
>
> Think of "org.pharo.asmjit.Instruction" vs "org.pharo.opal.Instruction"
>
> So you additionally need better and meaningful namespaces THAT SCALE AND ARE EASY TO UNDERSTAND
> combined with real packages (as objects, as Pharo already has).
We already have this, or the basis at least, in Squeak in the form of
Environments.
> Then we also need ABIA (Around, beginner, inner, after messages), multiple method
> categories, selector namespaces, possibility for visibility (like private methods, see [2]),
> unified annotations for classes/methods/variables and a few other ingredients from my
> personal wishlist and it may shape a different new future...
Squeak hasn't done this yet, but it should be possible to use
Environments to implement selector namespaces. We haven't done it yet
because Colin Putney's been really busy lately, and no one else has
had the time/energy to Just Do It. And if you have selector
namespaces, you have private methods, don't you?
frank
> The interesting part is not to add all kind of stuff to Smalltalk - the interesting
> part is what is the most minimalistic system to allow for something extensible
> and still flexible (even within the meta-system) so that one can bootstrap things on top.
>
> Bye
> T.
>
> [1] http://vimeo.com/75391990
> [2] http://smalltalkhub.com/#!/~CamilleTeruel/PrivateMethods
Sept. 24, 2014
[pharo-project/pharo-core] edfd40: 40248
by GitHub
Branch: refs/heads/4.0
Home: https://github.com/pharo-project/pharo-core
Commit: edfd405f882a831afc34830bc8f7f2de02a4601b
https://github.com/pharo-project/pharo-core/commit/edfd405f882a831afc34830b…
Author: Jenkins Build Server <board(a)pharo-project.org>
Date: 2014-09-24 (Wed, 24 Sep 2014)
Changed paths:
R Kernel.package/SmallInteger.class/class/plugin generation/ccgCanConvertFrom_.st
M Manifest-Core.package/extension/RBFutureDeprecationWarningRule/class/uniqueIdentifierName.st
M Refactoring-Critics.package/RBFutureDeprecationWarningRule.class/instance/accessing/rationale.st
A ScriptLoader40.package/ScriptLoader.class/instance/pharo - scripts/script248.st
A ScriptLoader40.package/ScriptLoader.class/instance/pharo - updates/update40248.st
M ScriptLoader40.package/ScriptLoader.class/instance/public/commentForCurrentUpdate.st
M System-Support.package/SmalltalkImage.class/instance/sources%2C change log/licenseStringTemplate.st
Log Message:
-----------
40248
14057 fix the description and unique name RBFutureDeprecationWarningRule.
https://pharo.fogbugz.com/f/cases/14057
14062 Remove SmallInteger class>>#ccgCanConvertFrom:
https://pharo.fogbugz.com/f/cases/14062
14056 Missing DejaVu copyright notices
https://pharo.fogbugz.com/f/cases/14056
http://files.pharo.org/image/40/40248.zip
Sept. 24, 2014
[pharo-project/pharo-core]
by GitHub
Branch: refs/tags/40248
Home: https://github.com/pharo-project/pharo-core
Sept. 24, 2014
Re: [Pharo-dev] deployment components (was "The Dilemma: Building a Futuristic GUI for Ephestos")
by phil@highoctane.be
In Wed, Sep 24, 2014 at 10:16 AM, Torsten Bergmann <astares(a)gmx.de> wrote:
> Craig Latta wrote:
> >Right, there's no need for anyone to use UUIDs when referring to
> >classes in Smalltalk expressions.
>
> Yes, exactly this. We still use regular names for the classes - but for
> the tools
> they have a distinguishable ID.
> Best is to use a UUID for the ID as it is unique from the beginning. So if
> you
> create a class "Foo" and I create one both are unqique by ID - even when
> using
> the same name.
>
> The "rest" is implemeting tooling support. When you write "Foo" in a
> workspace
> then the workspace either already has a naming context to resolve the name
> (see [1]
> or could provide you with a selection if there is more than one.
> Internally you could
> bind to the right class by using the ID.
>
> I hate prefixing the classes as we now do, I want to name the classes
> "Instruction"
> not "IRInstruction" in Opal or "AJInstruction" in AsmJIT, especially since
> "IR" and "AJ"
> do not really tell you anything. Smalltalk names should be understandable.
> Additionally
> we should have meaningfull (and also unique) names also for namespaces.
>
> Also the current three/two letter prefixing of classes that is used in
> Squeak or Pharo
> only scales well for small communities...
>
> When there are things I like in Java then it is the fact to use reverse
> domains
> for namespaces. It is easy, understandable and I could also easily check
> if there
> is a web location.
>
> This way a namespace "org.apache.maven" gives you something meaningful, I
> can even
> visit http://maven.apache.org/. Allows the community to easily scale with
> thousands of
> classes without having clashes.
> Think of "org.pharo.asmjit.Instruction" vs "org.pharo.opal.Instruction"
>
> So you additionally need better and meaningful namespaces THAT SCALE AND
> ARE EASY TO UNDERSTAND
> combined with real packages (as objects, as Pharo already has).
>
Actually, I am fine with the prefixes. Objective-C also works like that and
well, it hasn't exactly hampered its community to scale.
I have done my share of Java and yeah, sure, there are a lot of enterprise
grade things in there. So many that actual development and delivery usually
slows down to a crawl with lots of Java priests who confuse delivery of
business value with technical show off.
Also, we can rewrite prefixes pretty easily with the tooling.
>
> Then we also need ABIA (Around, beginner, inner, after messages), multiple
> method
> categories, selector namespaces, possibility for visibility (like private
> methods, see [2]),
> unified annotations for classes/methods/variables and a few other
> ingredients from my
> personal wishlist and it may shape a different new future...
The interesting part is not to add all kind of stuff to Smalltalk - the
> interesting
> part is what is the most minimalistic system to allow for something
> extensible
> and still flexible (even within the meta-system) so that one can bootstrap
> things on top.
Bye
> T.
>
> [1] http://vimeo.com/75391990
> [2] http://smalltalkhub.com/#!/~CamilleTeruel/PrivateMethods
>
>
Sept. 24, 2014
Re: [Pharo-dev] Interesting Date/Time Thread on Squeak Dev
by Mark Bestley
On 23/09/2014 08:48, Max Leske wrote:
>
> On 19.09.2014, at 19:14, Mark Bestley <st(a)bestley.co.uk> wrote:
>
>> On 19/09/2014 13:48, Max Leske wrote:
>>> Ok, so I read Chrisâ e-mail and Iâm intrigued.
>>>
>>> Sven, youâre still right about financial months being 30 days for instance but the thing is that the current implementation seems broken (or inconsisten at least) and doesnât honor that case either. *Not* making the change will not help us eitherâ¦
>>>
>>> So Iâd say: letâs do it. If somebody objects (or proposes a change) then we can handle that but at least we can claim that we try to give the users what we preach, like writing natural language like code (e.g. âx + 1 monthâ which is currently not possible).
>>>
>>> Thatâs my view at least. Also: weâre changing so much stuff in Pharo anyway all the time, I donât think this would hurt.
>>>
>>
>> That comment re 30 day months in financial is not totally correct.
>>
>> A common reason for calculating days in a financial calculation is for interest calculation and then you don't just need a number for the day difference but also for the number of days in a year. When I did this I think I had to support many ways of calculating the fraction of a year that was the difference between two dates depending on the interest basis (ie the contract terms) , Wikipedia gives 11 <http://en.wikipedia.org/wiki/Day_count_convention>
>>
>>
>> So I think that adding a financial number of days into a basic date object does not make sense as it will not be correct in many cases. The best way I have seen is to pass a daycount basis strategy class into the calculation and that strategy object does the calculation.
>
> I like the idea of using strategies. Although some might argue that such a change would unnecessarily bloat the code, strategies would give us the ability to define our âstandardâ calculation in a central place while enabling everyone to use their custom calculations.
>
It does not bloat the normal code - makes it smaller.You only need the
extra code if you need the extra financial calculations which most users
won't. Also it is not a unnecessary increase in code as if you neded
the calculations then you need the extra complexity
--
Mark
Sept. 24, 2014
Re: [Pharo-dev] I'm confused about Process>>isTerminated
by Max Leske
Iâve opened an issue on phogbugz: https://pharo.fogbugz.com/f/cases/14064/Improvements-to-checking-terminatio…
and created a slice. Iâd be grateful if you could take a look. There are three new tests that not only test #isTerminating but a lot of other expectations (like running the unwind blocks) too.
Cheers,
Max
On 22.09.2014, at 18:30, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
> Hi Max,
>
> phhh, that editor truncated my reply (that's my excuse and I'm sticking to it), so...
>
> On Mon, Sep 22, 2014 at 4:57 AM, Max Leske <maxleske(a)gmail.com> wrote:
> Hi Eliot,
>
> Thanks a lot for those explanations.
>
> On 18.09.2014, at 20:53, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
>
>> Hi Max,
>>
>> phhh, time zone differences suck ;-)
>>
>> On Thu, Sep 18, 2014 at 3:50 AM, Max Leske <maxleske(a)gmail.com> wrote:
>> Hi Eliot,
>>
>> On 18.09.2014, at 01:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
>>
>>> Hi Max,
>>>
>>> On Wed, Sep 17, 2014 at 1:59 PM, Max Leske <maxleske(a)gmail.com> wrote:
>>> Hi Eliot
>>>
>>>
>>> On 16.09.2014, at 20:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
>>>
>>>> Hi Max,
>>>>
>>>> On Tue, Sep 16, 2014 at 11:05 AM, Max Leske <maxleske(a)gmail.com> wrote:
>>>> Hi
>>>>
>>>> As always when I want to check if a process has died I get very confused by #isTerminated and Iâm wondering if I just donât get how itâs supposed to work or if there are others that share my confusion.
>>>>
>>>> Old implementation:
>>>>
>>>> isTerminated
>>>>
>>>> self isActiveProcess ifTrue: [^ false].
>>>> ^suspendedContext isNil
>>>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>>>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>>>> from value and there is nothing more to do."
>>>> suspendedContext isBottomContext
>>>> and: [ suspendedContext pc > suspendedContext startpc ] ]
>>>>
>>>>
>>>> Pharo 4 implementation:
>>>>
>>>> isTerminated
>>>> self isActiveProcess ifTrue: [^ false].
>>>> ^suspendedContext isNil
>>>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>>>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>>>> from value and there is nothing more to do.â
>>>> suspendedContext isBottomContext
>>>> and: [ suspendedContext isDead not â<âââââââââââââââââââââââââ new"
>>>> and: [ suspendedContext pc > suspendedContext startpc ] ] ]
>>>>
>>>>
>>>> The old implementation would break if the suspended context was dead (i.e. the pc was nil) because the send of #> would produce an MNU.
>>>> The new implementation doesnât fix that, even though it looks like it at first glance: if the pc is nil, the #> send will still happen -> MNU.
>>>>
>>>> Off the top of my head it would seem that it should be isDead or: [] not isDead not and:
>>>>
>>>> isTerminated
>>>> self isActiveProcess ifTrue: [^ false].
>>>> ^suspendedContext isNil
>>>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>>>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>>>> from value and there is nothing more to do.â
>>>> suspendedContext isBottomContext
>>>> and: [ suspendedContext isDead
>>>> or: [ suspendedContext pc > suspendedContext startpc ] ] ]
>>>
>>> Phew. Glad you see that the same way.
>>>
>>>> isDead
>>>> ^ pc isNil
>>>>
>>>> and maybe (suspendedContext pc ifNil: [true] ifNotNil: [:pc| pc > suspendedContext startpc]) is more obvious.
>>>>
>>>> Anyway, neither implementation will reliably tell me if the process has been terminated:
>>>> - an inactive process will be suspended when #terminate is sent and report that it has not been terminated (#isSuspended -> true, #isTerminated -> false)
>>>>
>>>> except that it *hasn't* been terminated, it is merely in the process of termination. It isn't terminated until all unwind blocks have run, right?
>>>
>>> True. Easy to forget when you can just kill -9 on the console⦠:)
>>>
>>>>
>>>> - a properly terminated process will raise an MNU (although apparently not always�)
>>>>
>>>> but that's a bug the change I suggested will fix.
>>>>
>>>> - all the states in between: no clue
>>>>
>>>> I would like to know two things:
>>>> 1. how can I check if a process has already *received* a #terminate? (I would then assume that the process will die eventually)
>>>>
>>>> I don't think you can without putting a critical section around terminate and adding some process-specific variable that is set when you send terminate. termination is not instantaneous (unwind blocks have to be run), so it is potentially interruptible.
>>>
>>> Iâve thought about this a bit. I wouldnât really care if I donât get a correct answer about the termination status immediately but I want to have it before the process terminates. In case of something like the following:
>>>
>>> ([ 10 seconds asDelay wait ] forkAt: 11) terminate
>>>
>>> it can (potentially) take a very long time for the process to terminate. So if I have to poll 3 or 4 times thatâs ok but I donât want to wait for minutes.
>>> One solution would be to take your idea of the variable, but without the critical block:
>>>
>>> terminate
>>> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>>>
>>> | ctxt unwindBlock oldList |
>>> terminating := true. â<âââââââââââââââââââââââââââââââââââ changed"
>>> self isActiveProcess
>>> ifTrue: [
>>> ctxt := thisContext.
>>> [ ctxt := ctxt findNextUnwindContextUpTo: nil.
>>> ctxt isNil ] whileFalse:
>>> [ (ctxt tempAt: 2) ifNil:
>>> [ ctxt tempAt: 2 put: nil.
>>> unwindBlock := ctxt tempAt: 1.
>>> thisContext terminateTo: ctxt.
>>> unwindBlock value ]].
>>> thisContext terminateTo: nil.
>>> self suspend ]
>>> ifFalse: [
>>> "Always suspend the process first so it doesn't accidentally get woken up"
>>> oldList := self suspend.
>>> suspendedContext ifNotNil:[
>>> "Figure out if we are terminating the process while waiting in Semaphore>>critical:
>>> In this case, pop the suspendedContext so that we leave the ensure: block inside
>>> Semaphore>>critical: without signaling the semaphore."
>>> (oldList class == Semaphore and:[
>>> suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[
>>> suspendedContext := suspendedContext home.].
>>>
>>> "If we are terminating a process halfways through an unwind, try to complete that unwind block first."
>>> (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [ :outer |
>>> (suspendedContext findContextSuchThat: [ :c | c closure == (outer tempAt: 1)])
>>> ifNotNil: [ :inner |
>>> "This is an unwind block currently under evaluation"
>>> suspendedContext runUntilErrorOrReturnFrom: inner ]].
>>> ctxt := self popTo: suspendedContext bottomContext.
>>> ctxt == suspendedContext bottomContext ifFalse: [
>>> self debug: ctxt title: 'Unwind error during termination']] ].
>>>
>>>
>>>
>>> isTerminating
>>> ^ terminating ifNil: [ ^ false ]
>>>
>>>
>>> With this small modification I can run the example from above and immediately see that it will die eventually.
>>>
>>> Iâm aware that one process might not see the change to the variable immediately but as I said, I wouldnât really care.
>>>
>>>
>>> What do you think?
>>>
>>> Yes that looks good. But given that branches are atomic (ifTrue: is not a send) why not do
>>>
>>> Process>>initialize
>>> terminating := false.
>>>
>>> terminate
>>> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>>>
>>> | ctxt unwindBlock oldList |
>>> terminating
>>> ifTrue: [self error: 'Process is already terminated, or being terminated']
>>> ifFalse: [terminating := true].
>>> self isActiveProcess
>>> ifTrue:
>>> ...
>>>
>>> ?
>>>
>>> I would suggest a status inst var, as in
>>>
>>> Process>>initialize
>>> status := nil
>>>
>>> terminate
>>> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>>>
>>> | ctxt unwindBlock oldList |
>>> status == #terminating
>>> ifTrue: [self error: 'Process is already terminated, or being terminated']
>>> ifFalse: [status := terminating].
>>> self isActiveProcess
>>> ifTrue:
>>> ...
>>>
>>> but the temptation then is to have lots of different status values and I'm leery of introducing that kind of complication without a strong justification.
>>
>>
>> Iâve worked a bit on an implementation along your suggestions. I wrote a test which looks like this:
>>
>> testIsTerminated
>> | proc |
>> proc := [ Semaphore new wait ] forkAt: 30.
>> self deny: proc isSuspended.
>> self deny: proc isTerminating.
>> self deny: proc isTerminated.
>>
>> proc terminate.
>> self deny: proc isTerminated.
>> self assert: proc isSuspended.
>> self assert: proc isTerminating.
>>
>> [ proc isTerminated ] whileFalse: [ 1 second asDelay wait ]. â<âââââââââââ ???"
>>
>> self assert: proc isTerminated.
>> self assert: proc isTerminating
>>
>> The test works AFAICT (apart from the loopâ¦) but I want to also have a check after the process has terminated. Is there some reliable way to wait for a process to die? I tried something like this for example:
>>
>> proc run.
>> self assert: proc isTerminated.
>>
>> But that locks up the active process (obviously) until I interrupt it manually. If there is such a way, I could also add a method that lets a process x wait for the completion of a process y for example (or not, depending on how difficult it is :) )
>>
>> I can't see anything to do other than waiting. One thing is to run the process at as close to user priority as possible, so I would say
>>
>> proc := [ Semaphore new wait ] forkAt: Processor activePriority - 1.
>>
>> Another important thing is that you're not giving your process a chance to run before you test for it not terminating. So adding a yield after the first set of asserts and then repeating them is good:
>>
>> started := false. proc := [ started := true. Semaphore new wait ] forkAt: 30.
>> self deny: proc isSuspended.
>> self deny: proc isTerminating.
>> self deny: proc isTerminated.
>>
>> (Delay forMilliseconds: 10) wait. self assert: started.
>> self deny: proc isSuspended.
>> self deny: proc isTerminating.
>> self deny: proc isTerminated.
>>
>>
>> Another thing might be to boost its priority to make sure it finishes (except that that'll probably have no effect because IIRC right now the terminator runs the termination). So you could say
>>
>> proc terminate.
>> self deny: proc isTerminated.
>> self assert: proc isSuspended.
>> self assert: proc isTerminating.
>>
>> process priority: Processor activePriority + 1.
>>
>> [ proc isTerminated ] whileFalse: [ 1 second asDelay wait ].
>>
>> Further I'd want to test that unwind blocks have been run so I'd say
>>
>> testIsTerminated
>> | proc started unwound terminator |
>> unwound := false. proc := [ started := true. [Semaphore new wait]
>> ensure: [terminator := Processor activeProcess.
>> unwound := true] ]
>> forkAt: Processor activePriority - 1.
>> self deny: proc isSuspended.
>> self deny: proc isTerminating.
>> self deny: proc isTerminated.
>>
>> (Delay forMilliseconds: 10) wait. "Alloc proc to run; there shouldnt be too much else going on so this delay should suffice"
>>
>> self assert: started.
>> self deny: proc isSuspended.
>> self deny: proc isTerminating.
>> self deny: proc isTerminated.
>>
>> proc terminate.
>> proc priority: Processor activePriority + 1. "This may have no effect; termination may be executed by the terminator rather than the terminatee; ys, this is a bug"
>> self deny: proc isTerminated.
>> self assert: proc isSuspended.
>> self assert: proc isTerminating.
>>
>> (Delay forMilliseconds: 10) wait. "Allow proc to terminate; there shouldnt be too much else going on so this delay should suffice"
>>
>> self assert: proc isTerminated.
>> self assert: proc isTerminating.
>> self assert: unwound.
>> self assert: terminator == proc. "But this should be made an expected failure; I don't know how to do that in SUnitâ¦"
>
> From your comments I expected this last statement to fail but actually it doesnât. I guess thatâs a good sign (?).
>
>>
>> and google's mail text editor *SUCKS*!!!!
>
> lol :p
>
> I noticed something else regarding terminated processes that have never run and Iâm not sure if thatâs not a bug:
> When I suspend a process (that has never run) that is not the active process, I can reliably reproduce that the entire #terminate method is being executed. The processâ suspendedContext is the bottom context (as it should be). However, the pc is equal to the startpc, since that process never had a chance to to anything. The result is that #isTerminated will answer false, even though the process is technically terminated.
> One side effect of this is that itâs impossible to do something like â[ proc isTerminated ] whileFalse: [ 1 second asDelay wait ].â because that will not terminate for all processes. Luckily those processes can be garbage collected regardless of what #isTerminated says.
>
> One obvious fix would be to set the pc of the suspendedContext to nil but Iâm not sure thatâs a good idea.
>
> What do you think?
>
> I think that's fine.
>
> Cheers,
> Max
>> Cheers,
>> Max
>>> Cheers,
>>> Max
>>> 2. how can I check if a process is *actually* dead? (in case a âhalf deadâ process will still unwind or whatever)
>>>
>>> see above.
>>>
>>> What would be necessary to make those tests (or better ones) possible (rewrite the whole process implementation?)?
>>>
>>> Cheers,
>>> Max
>>> --
>>> best,
>>> Eliot
>>> --
>>> best,
>>> Eliot
>> --
>> best,
>> Eliot
> --
> best,
> Eliot
Sept. 24, 2014