Re: VisualWorks and support for native multi-threading

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

RE: VisualWorks and support for native multi-threading

Paul Baumann
Pass-by-value is the easiest and most common way. You'd have to use
pass-by-reference for this kind of stuff though--correct me if I'm
wrong. By-reference means overhead tracking remote identity. It means
weak references. It means export sets. It means object-session
affiliation. It means lookup tables. It means remote debugging hooks. It
means proxies. It means replication rules. It means change tracking and
propagation.

There is a lot of parts involved but they are understood issues and it
is possible to implement them with low overhead. There are probably a
dozen of implementations out there to do this in the Smalltalk world.

A key success factor for replication and distributed processing is in
the quality of the distribution. I'm thinking you could turn on a flag
that would add high-overhead tracking. The tracking would be turned off
and would be applied to optimize the existing code. The differentiating
factor between this and other approaches is that distribution rules can
be determined automatically rather than by programmer assumption. This
is kind of optimization is currently manual in the implementations I'm
familiar with.

Paul Baumann

-----Original Message-----
From: John Treble [mailto:[hidden email]]
Sent: Friday, February 23, 2007 10:33 AM
To: 'Martin Kobetic'
Cc: [hidden email]
Subject: RE: VisualWorks and support for native multi-threading

> The one thing you'd need to be careful about is making sure that
> things
get passed by value (even in local calls) instead of by reference.


Martin et al,

It's not my intention to hijack this thread, but I've often wondered in
what STST scenarios it makes more sense to pass by reference than value.
I have always done it by value.  TIA.

John Treble


> -----Original Message-----
> From: Martin Kobetic [mailto:[hidden email]]
> Sent: February 23, 2007 9:44 AM
> To: Ladislav Lenart
> Cc: [hidden email]
> Subject: Re: VisualWorks and support for native multi-threading
>
> I feel that using something like the Actalk framework and a
> transparent distribution framework, e.g. Opentalk-STST you can get
> pretty close to the Erlang model. The one thing you'd need to be
> careful about is making sure that things get passed by value (even in
> local calls) instead of by reference. Although I have doubts about
> that being a universal rule. What happens in Erlang when you pass some

> kind of system object like the scheduler ? I feel that maybe the
> programmer should fine tune what gets passed by value and what by
reference.

>
> Ladislav Lenart wrote:
> > Travis Griggs wrote:
> >> On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
> >>
> >>> [Grr, my reply last night went to Travis only.  Sorry Paul...]
> >>>
> >>> Travis is quite right.  The point to remember about multicore
> >>> processors is that the chip still only has one interface to main
> >>> memory and each core shares that interface (and the cache and
> >>> (typically) TLBs) - remember many are socket-compatible with
> >>> single-core processors.  If one has a memory-bound application
> >>> throwing a multicore at it can do nothing to increase performance.
> >>> Large symbolic applications, a mainstay of server applications in
> >>> OO languages, are such beasts.
> >>>
> >>> Whether this point is easy to enunciate against the marketing
> >>> noise is, however, an entirely different question.
> >>
> >> The language of note that would seem to come closest to the notion
> >> of "don't worry about your threading" would be Erlang (I'm sure
> >> there are more noteworthy research languages, but I'm aware of
> >> known with any degree of popularity). The Erlang guys were recently

> >> excited about the ability to exploit multi cores. You can google
> >> for the results. One of the interesting sites I found was a SIP
> >> stack which had no coding changes made to it. When run on a quad
> >> core, it ran 1.8 times faster than the single core.
> >
> > The Erlang is definitely worth trying but it is certainly NOT one of

> > those "don't worry about your threading" languages, quite the
contrary.

> > But because it uses completely different idiom, you don't have to
> > mess with semaphores and all that (ugly low-level) stuff. In fact
> > these are not present in the language at all. In Erlang, each
> > process has its
> mailbox
> > for all incoming messages and it can decide when and what messages
> > to
> read
> > from it. It can also send asynchronous messages to other processes.
> > And that's pretty much it. The rest is pure functional programming
> > of the internals of the process that operates on its internal state.

> > But you can still encounter race conditions only in slightly
different form:

> >
> >   Process A sends message to B and C. When B receives the message,
> >   it queries C for something that C should compute as a result of
> >   receiving the message from A. But there is no guarantee in which
> >   order will C receive the message from A and the other (query)
> >   from B.
> >
> > The language guarantees only that when process A sends messages to
> > process B, B will always receive them in the order their were sent.
> >
> > But working, debugging and testing multiple processes is really MUCH

> > easier in Erlang than in anything else I've ever used. It (almost)
> > works like what you would model as objects in Smalltalk, you would
> > model as processes in Erlang.
> >
> > The smart decision the Erlang authors made was that there will be no

> > memory sharing and processes and scheduler will be part of the
language.
> > This enabled them to create a high-level layer which makes the work
> > with processes location transparent - once you have a pid of a
> > process, you can send it messages no matter where it really is (on
> > which node). This transparency is really great, because once you
> > have a program, you can run it on more nodes (computers) or start
one node on multicore CPU.
> >
> > Ladislav Lenart
> >
> >
 
 
 
--------------------------------------------------------
This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.  
 

Reply | Threaded
Open this post in threaded view
|

RE: VisualWorks and support for native multi-threading

Paul Baumann
In reply to this post by kobetic
Martin wrote:
>>I feel that maybe the programmer should fine tune what gets passed by
value and what by reference.

Excellent point. Magnitude subclasses should be passed by value. I think
you need pass by reference for the objects that have less of a data feel
to them. Some existing frameworks pass things like strings by-reference
and I think that is unnecessary for 99.9% of the uses of strings in
typical Smalltalk dialects.

Paul Baumann

-----Original Message-----
From: Martin Kobetic [mailto:[hidden email]]
Sent: Friday, February 23, 2007 9:44 AM
To: Ladislav Lenart
Cc: [hidden email]
Subject: Re: VisualWorks and support for native multi-threading

I feel that using something like the Actalk framework and a transparent
distribution framework, e.g. Opentalk-STST you can get pretty close to
the Erlang model. The one thing you'd need to be careful about is making
sure that things get passed by value (even in local calls) instead of by
reference. Although I have doubts about that being a universal rule.
What happens in Erlang when you pass some kind of system object like the
scheduler ? I feel that maybe the programmer should fine tune what gets
passed by value and what by reference.

Ladislav Lenart wrote:

> Travis Griggs wrote:
>> On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
>>
>>> [Grr, my reply last night went to Travis only.  Sorry Paul...]
>>>
>>> Travis is quite right.  The point to remember about multicore
>>> processors is that the chip still only has one interface to main
>>> memory and each core shares that interface (and the cache and
>>> (typically) TLBs) - remember many are socket-compatible with
>>> single-core processors.  If one has a memory-bound application
>>> throwing a multicore at it can do nothing to increase performance.
>>> Large symbolic applications, a mainstay of server applications in OO

>>> languages, are such beasts.
>>>
>>> Whether this point is easy to enunciate against the marketing noise
>>> is, however, an entirely different question.
>>
>> The language of note that would seem to come closest to the notion of

>> "don't worry about your threading" would be Erlang (I'm sure there
>> are more noteworthy research languages, but I'm aware of known with
>> any degree of popularity). The Erlang guys were recently excited
>> about the ability to exploit multi cores. You can google for the
>> results. One of the interesting sites I found was a SIP stack which
>> had no coding changes made to it. When run on a quad core, it ran 1.8

>> times faster than the single core.
>
> The Erlang is definitely worth trying but it is certainly NOT one of
> those "don't worry about your threading" languages, quite the
contrary.
> But because it uses completely different idiom, you don't have to mess

> with semaphores and all that (ugly low-level) stuff. In fact these are

> not present in the language at all. In Erlang, each process has its
> mailbox for all incoming messages and it can decide when and what
> messages to read from it. It can also send asynchronous messages to
> other processes. And that's pretty much it. The rest is pure
> functional programming of the internals of the process that operates
> on its internal state. But you can still encounter race conditions
only in slightly different form:

>
>   Process A sends message to B and C. When B receives the message,
>   it queries C for something that C should compute as a result of
>   receiving the message from A. But there is no guarantee in which
>   order will C receive the message from A and the other (query)
>   from B.
>
> The language guarantees only that when process A sends messages to
> process B, B will always receive them in the order their were sent.
>
> But working, debugging and testing multiple processes is really MUCH
> easier in Erlang than in anything else I've ever used. It (almost)
> works like what you would model as objects in Smalltalk, you would
> model as processes in Erlang.
>
> The smart decision the Erlang authors made was that there will be no
> memory sharing and processes and scheduler will be part of the
language.
> This enabled them to create a high-level layer which makes the work
> with processes location transparent - once you have a pid of a
> process, you can send it messages no matter where it really is (on
> which node). This transparency is really great, because once you have
> a program, you can run it on more nodes (computers) or start one node
on multicore CPU.
>
> Ladislav Lenart
>
>
 
 
 
--------------------------------------------------------
This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.  
 

Reply | Threaded
Open this post in threaded view
|

RE: VisualWorks and support for native multi-threading

jarober
In reply to this post by Joerg Beekmann, DeepCove Labs (YVR)
I think I'd have to answer this with "it depends".  In BottomFeeder,
I spawn off N Smalltalk processes with each update cycle - each is an
HTTP query of indeterminate duration, and each updates a discrete
object.  I've not really had problems with this (beyond the VM
blocking on DNS lookups, but that's unrelated).

Now, having each of those threads be a Smalltalk process is pretty
simple, and pretty easy to control.  If they were OS threads, I
couldn't possibly manage it that way, even on a 2 or 4 processor system.

At 10:48 AM 2/23/2007, you wrote:

>Reading this tread it seems it is missing the point. The issue with
>multithreading as implemented in Smalltalk is not performance,
>though more is always better, but the semantics. Semaphores and
>shared memory are too difficult to work with. What should be
>explored is how to add better, and by that I mean easier to work
>with semantics, for multithreading into Smalltalk. If Smalltalk
>provided a conceptually manageable way to manage even 100 threads we
>would be way ahead. I don't even think there are that many options:
>
>    * Transactional memory; this keeps shared memory but give better
> tools for managing conflicts.
>    * A pure Actor/CSP based notion of concurrency such as is used in Erlang
>    * Hybrid approach where the normal message sends are single
> threaded but message sends to other threads have special semantics.
>
>I like option 3. This approach is a bit like the notion of using
>multiple images communication via Open Talk but they all happen to
>reside in the memory space sharing objects where possible.
>
>
>----------
>From: Travis Griggs [mailto:[hidden email]]
>Sent: February 22, 2007 7:13 PM
>To: VW NC
>Subject: Re: VisualWorks and support for native multi-threading
>
>On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
>
>
>[Grr, my reply last night went to Travis only.  Sorry Paul...]
>
>Travis is quite right.  The point to remember about multicore
>processors is that the chip still only has one interface to main
>memory and each core shares that interface (and the cache and
>(typically) TLBs) - remember many are socket-compatible with
>single-core processors.  If one has a memory-bound application
>throwing a multicore at it can do nothing to increase
>performance.  Large symbolic applications, a mainstay of server
>applications in OO languages, are such beasts.
>
>Whether this point is easy to enunciate against the marketing noise
>is, however, an entirely different question.
>
>The language of note that would seem to come closest to the notion
>of "don't worry about your threading" would be Erlang (I'm sure
>there are more noteworthy research languages, but I'm aware of known
>with any degree of popularity). The Erlang guys were recently
>excited about the ability to exploit multi cores. You can google for
>the results. One of the interesting sites I found was a SIP stack
>which had no coding changes made to it. When run on a quad core, it
>ran 1.8 times faster than the single core.
>
>--
>Travis Griggs
>Objologist
>One man's blue plane is another man's pink plane.
>
>
>

<Talk Small and Carry a Big Class Library>
James Robertson, Product Manager, Cincom Smalltalk
http://www.cincomsmalltalk.com/blog/blogView

Reply | Threaded
Open this post in threaded view
|

Re: VisualWorks and support for native multi-threading

Eliot Miranda-2
In reply to this post by Paul Baumann


On 2/22/07, Paul Baumann <[hidden email]> wrote:
 
Perhaps what GemFire addresses through the socket layer. I'd assumed things like that had already been worked out efficiently at the hardware level. I guess I had read the hardware marketing noise about shared memory cache and such so I didn't catch those details. Thanks for the information. Does it seem like those issues might be worked out any time soon? If not, it is a replication issue that has a whole set of issues and costs that are fortunately very familiar.
 
This article was recently brought to my attention. I fear it blows the possibility of a casual entrance. Efficiency would be critical to get noticed.
 
<a href="http://mlee888.wordpress.com/2006/03/31/java-performance-in-dual-coremultiprocessor-environment/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"> http://mlee888.wordpress.com/2006/03/31/java-performance-in-dual-coremultiprocessor-environment/


Well this poor soul has yet to realise that to a first approximation a 64-bit implementation of a symbolic program moves twice as much data as a 32-bit implementation and hence performance of memory-bound applications drops when moving to 64-bits (to a first approximation by a factor of two :) ).  I've talked about this before with the VW 64-bit application and how through using a revised object representation and immediate doubles I was able to restrict the slow-down to +15% on the x86-64.  You may get what you pay for, but with 64-bit computing you pay for what you get ;)

I'm thinking that performance could be achieved by being selective about what work gets done in separate processors. Doing every operation through a queue was interesting for research but probably not practical for real applications. It can be optimizing.
 
Sorry, I'm getting out of my realm of experience. I hope somebody figures it out. It seems like interesting work.
 
Paul Baumann 
 


From: Eliot Miranda [mailto:[hidden email]]
Sent: Thursday, February 22, 2007 7:20 PM
To: VW NC
Subject: Re: VisualWorks and support for native multi-threading

[Grr, my reply last night went to Travis only.  Sorry Paul...]

Travis is quite right.  The point to remember about multicore processors is that the chip still only has one interface to main memory and each core shares that interface (and the cache and (typically) TLBs) - remember many are socket-compatible with single-core processors.  If one has a memory-bound application throwing a multicore at it can do nothing to increase performance.  Large symbolic applications, a mainstay of server applications in OO languages, are such beasts.

Whether this point is easy to enunciate against the marketing noise is, however, an entirely different question.

On 2/21/07, Travis Griggs <[hidden email]> wrote:
On Feb 21, 2007, at 16:30, Paul Baumann wrote:

Travis wrote:
In a rosy world, where the 24% really was realizable, the overhead of adding the "lists of messages" and async return could add up to 24% before it was a wash. And it then be only a wash, not worth the added complexity. We'd have to have it down in more like the 5% overhead realm, for it to make any appreciable improvement for the system. Furthermore, as the number 24% is "drastically reduced" the amount of overhead you can spend on this goes down too. So if we're really only going to get say 10% realistically, we need more like 2% overhead.
 
Consider the obvious mega trend that has recently begun...
 
Would anyone want buy a computer today that isn't at least dual core? In ten years the market may expect hundreds or thousands of cores for the typical PC. That creates a market demand for software that can take advantage of the parallel processing power. 24% overhead is nothing if it means work can be automatically distributed over 100 cores that would otherwise be idle. Similarly, 64-bit has 100% space overhead compared to 32-bit but the overhead is increasingly worth the cost in order to increase capacity.
 

But... I don't understand what you're saying. Or am confused that you didn't really read what I wrote. 24%. That means that at absolute best your other cpu could be working ~25% of the time. 75% of it's cycles are wasted. If you throw a quad core at it, you get to have each of the extra 3 cpus run at 8% of their ability. A pretty high cost to pay for all these cores, just to have them rarely used.

But the real killer Paul is that little statement "drastically reduced." I was generous. I gave it a 1/2 cut. In reality, when I see a phrase like that, I read "an order of magnitude" less. So you're excited about rewriting the VM, dealing with the deferred side affects edge cases that i gave an example of, all so your new quad core can swap off 0.6% of the execution time to your other three processors transparently?

I didn't say that I thought doing something about multithreading was a bad idea. What I questioned was the notion that there should be some sort of transparent magic that just opens up all of these multi cores to us. Or rather, I questioned the particular paper cited by Reinout. Sure, I'd love a magic wand that did that. So your preaching to the choir when it comes to wishing there were easier ways to take advantage of the growing number of multi cores. But you're preaching to the skeptic if you think that the Merlin thing is some low hanging fruit that we should turn-n-burn on.

--
Travis Griggs
Objologist
"I think that we should be men first, and subjects afterward." - Henry David Thoreau




 

 

 


This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.


Reply | Threaded
Open this post in threaded view
|

RE: VisualWorks and support for native multi-threading

Joerg Beekmann, DeepCove Labs (YVR)
In reply to this post by jarober

>
> I think I'd have to answer this with "it depends".  In BottomFeeder,
> I spawn off N Smalltalk processes with each update cycle - each is an
> HTTP query of indeterminate duration, and each updates a discrete
> object.  I've not really had problems with this (beyond the VM
> blocking on DNS lookups, but that's unrelated).

My point is that the nature of the shared memory/monitor implementation
of concurrency forces you into needing to ensure in your mind things
like "each updates a discrete object".

Anymore complicated and it quickly becomes very difficult to ensure
correctness. I'm sure many on the list recall first discovering
processes and parallelism, thinking it was great, using it on a project,
getting it all wrong and deciding that in the future to stick to a
single thread.

Until that changes parallel processing will remain a technique for niche
problems.

> Now, having each of those threads be a Smalltalk process is pretty
> simple, and pretty easy to control.  If they were OS threads, I
> couldn't possibly manage it that way, even on a 2 or 4 processor
system.

>
> At 10:48 AM 2/23/2007, you wrote:
> >Reading this tread it seems it is missing the point. The issue with
> >multithreading as implemented in Smalltalk is not performance,
> >though more is always better, but the semantics. Semaphores and
> >shared memory are too difficult to work with. What should be
> >explored is how to add better, and by that I mean easier to work
> >with semantics, for multithreading into Smalltalk. If Smalltalk
> >provided a conceptually manageable way to manage even 100 threads we
> >would be way ahead. I don't even think there are that many options:
> >
> >    * Transactional memory; this keeps shared memory but give better
> > tools for managing conflicts.
> >    * A pure Actor/CSP based notion of concurrency such as is used in
> Erlang
> >    * Hybrid approach where the normal message sends are single
> > threaded but message sends to other threads have special semantics.
> >
> >I like option 3. This approach is a bit like the notion of using
> >multiple images communication via Open Talk but they all happen to
> >reside in the memory space sharing objects where possible.
> >
> >
> >----------
> >From: Travis Griggs [mailto:[hidden email]]
> >Sent: February 22, 2007 7:13 PM
> >To: VW NC
> >Subject: Re: VisualWorks and support for native multi-threading
> >
> >On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
> >
> >
> >[Grr, my reply last night went to Travis only.  Sorry Paul...]
> >
> >Travis is quite right.  The point to remember about multicore
> >processors is that the chip still only has one interface to main
> >memory and each core shares that interface (and the cache and
> >(typically) TLBs) - remember many are socket-compatible with
> >single-core processors.  If one has a memory-bound application
> >throwing a multicore at it can do nothing to increase
> >performance.  Large symbolic applications, a mainstay of server
> >applications in OO languages, are such beasts.
> >
> >Whether this point is easy to enunciate against the marketing noise
> >is, however, an entirely different question.
> >
> >The language of note that would seem to come closest to the notion
> >of "don't worry about your threading" would be Erlang (I'm sure
> >there are more noteworthy research languages, but I'm aware of known
> >with any degree of popularity). The Erlang guys were recently
> >excited about the ability to exploit multi cores. You can google for
> >the results. One of the interesting sites I found was a SIP stack
> >which had no coding changes made to it. When run on a quad core, it
> >ran 1.8 times faster than the single core.
> >
> >--
> >Travis Griggs
> >Objologist
> >One man's blue plane is another man's pink plane.
> >
> >
> >
>
> <Talk Small and Carry a Big Class Library>
> James Robertson, Product Manager, Cincom Smalltalk
> http://www.cincomsmalltalk.com/blog/blogView

Reply | Threaded
Open this post in threaded view
|

Re[2]: VisualWorks and support for native multi-threading

Michael Lucas-Smith
In reply to this post by jarober
From what I'm hearing.. James Robertson is saying the easiest and most
approachable way to utilise multiple cores is to run multiple images.
At the time time, we have people pushing the Erlang model - which
enforces strict isolation of the threads.

So we're actually talking about the same thing here. If the controls
to spawn off another running VM were internalized in Smalltalk -
sharing the same image base (perm space - does that work on 32bit VMs
too?) - then some light weight object-copy mechanism for sending
messages between the threads (STST could certainly be a good starting
point).

That combination would remove the complexity of managing multiple
images, because to make a new one you'd do something like newThread
:= ObjectMemory fork. There wouldn't be a giant memory overhead if
perm space were used by the image and we also pick up the same Erland
model as well as keeping our brilliant Smalltalk model.

Sounds great to me. And would it be that much harder to use than a
green thread (of which you can still utilise) .. not really. STST is
pretty easy to use. And given in this scenario you don't need to
"setup" STST (since it's all preconfigured for extrathread
communications), it really would be that simple.

As an added bonus, we'd also be able to do something Erlang cannot do
easily - pass by reference between our threads.

I'd say the only thing stopping this kind of capability ending up in
VW7.6 would be whether perm space memory sharing will work on 32bit
platforms?

Cheers,
Michael

> I think I'd have to answer this with "it depends".  In BottomFeeder,
> I spawn off N Smalltalk processes with each update cycle - each is an
> HTTP query of indeterminate duration, and each updates a discrete
> object.  I've not really had problems with this (beyond the VM
> blocking on DNS lookups, but that's unrelated).

> Now, having each of those threads be a Smalltalk process is pretty
> simple, and pretty easy to control.  If they were OS threads, I
> couldn't possibly manage it that way, even on a 2 or 4 processor system.

> At 10:48 AM 2/23/2007, you wrote:
>>Reading this tread it seems it is missing the point. The issue with
>>multithreading as implemented in Smalltalk is not performance,
>>though more is always better, but the semantics. Semaphores and
>>shared memory are too difficult to work with. What should be
>>explored is how to add better, and by that I mean easier to work
>>with semantics, for multithreading into Smalltalk. If Smalltalk
>>provided a conceptually manageable way to manage even 100 threads we
>>would be way ahead. I don't even think there are that many options:
>>
>>    * Transactional memory; this keeps shared memory but give better
>> tools for managing conflicts.
>>    * A pure Actor/CSP based notion of concurrency such as is used in Erlang
>>    * Hybrid approach where the normal message sends are single
>> threaded but message sends to other threads have special semantics.
>>
>>I like option 3. This approach is a bit like the notion of using
>>multiple images communication via Open Talk but they all happen to
>>reside in the memory space sharing objects where possible.
>>
>>
>>----------
>>From: Travis Griggs [mailto:[hidden email]]
>>Sent: February 22, 2007 7:13 PM
>>To: VW NC
>>Subject: Re: VisualWorks and support for native multi-threading
>>
>>On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
>>
>>
>>[Grr, my reply last night went to Travis only.  Sorry Paul...]
>>
>>Travis is quite right.  The point to remember about multicore
>>processors is that the chip still only has one interface to main
>>memory and each core shares that interface (and the cache and
>>(typically) TLBs) - remember many are socket-compatible with
>>single-core processors.  If one has a memory-bound application
>>throwing a multicore at it can do nothing to increase
>>performance.  Large symbolic applications, a mainstay of server
>>applications in OO languages, are such beasts.
>>
>>Whether this point is easy to enunciate against the marketing noise
>>is, however, an entirely different question.
>>
>>The language of note that would seem to come closest to the notion
>>of "don't worry about your threading" would be Erlang (I'm sure
>>there are more noteworthy research languages, but I'm aware of known
>>with any degree of popularity). The Erlang guys were recently
>>excited about the ability to exploit multi cores. You can google for
>>the results. One of the interesting sites I found was a SIP stack
>>which had no coding changes made to it. When run on a quad core, it
>>ran 1.8 times faster than the single core.
>>
>>--
>>Travis Griggs
>>Objologist
>>One man's blue plane is another man's pink plane.
>>
>>
>>

> <Talk Small and Carry a Big Class Library>
> James Robertson, Product Manager, Cincom Smalltalk
> http://www.cincomsmalltalk.com/blog/blogView

Reply | Threaded
Open this post in threaded view
|

RE: Re[2]: VisualWorks and support for native multi-threading

Joerg Beekmann, DeepCove Labs (YVR)
> -----Original Message-----
> From: Michael Lucas-Smith [mailto:michael.lucas-
> [hidden email]]
> Sent: February 23, 2007 2:37 PM
> To: James Robertson
> Cc: [hidden email]
> Subject: Re[2]: VisualWorks and support for native multi-threading
>
> From what I'm hearing.. James Robertson is saying the easiest and most
> approachable way to utilise multiple cores is to run multiple images.
> At the time time, we have people pushing the Erlang model - which
> enforces strict isolation of the threads.
>
> So we're actually talking about the same thing here. If the controls
> to spawn off another running VM were internalized in Smalltalk -
> sharing the same image base (perm space - does that work on 32bit VMs
> too?) - then some light weight object-copy mechanism for sending
> messages between the threads (STST could certainly be a good starting
> point).

You don't actually need to copy anything as long as it isn't changed
after being passed. It may be possible to use immutability for this [he
says waiving arms], basically pass the object to the other thread but as
soon as it is modified in either a new copy needs to be created. Is that
what you intend when you say:  "As an added bonus, we'd also be able to
do something Erlang cannot do easily - pass by reference between our
threads."

Another advantage of being more coarse grained and "developer"
controlled about parallelism is that with some care (avoiding the fine
grained distributed object model of death) you can architect so that
parallelizing internally or to remote machines is a configuration
option.

Basically this is all very similar to Limbo. In Limbo threads
communicate via channels and can pass anything over a channel, even
another channel. After passing a message to a channel they wait (or
not). Combined with a non-blocking read on multiple channels at once
makes for a very nice programming model.


>
> That combination would remove the complexity of managing multiple
> images, because to make a new one you'd do something like newThread
> := ObjectMemory fork. There wouldn't be a giant memory overhead if
> perm space were used by the image and we also pick up the same Erland
> model as well as keeping our brilliant Smalltalk model.
>
> Sounds great to me. And would it be that much harder to use than a
> green thread (of which you can still utilise) .. not really. STST is
> pretty easy to use. And given in this scenario you don't need to
> "setup" STST (since it's all preconfigured for extrathread
> communications), it really would be that simple.
>
> As an added bonus, we'd also be able to do something Erlang cannot do
> easily - pass by reference between our threads.
>
> I'd say the only thing stopping this kind of capability ending up in
> VW7.6 would be whether perm space memory sharing will work on 32bit
> platforms?
>
> Cheers,
> Michael
>
> > I think I'd have to answer this with "it depends".  In BottomFeeder,
> > I spawn off N Smalltalk processes with each update cycle - each is
an
> > HTTP query of indeterminate duration, and each updates a discrete
> > object.  I've not really had problems with this (beyond the VM
> > blocking on DNS lookups, but that's unrelated).
>
> > Now, having each of those threads be a Smalltalk process is pretty
> > simple, and pretty easy to control.  If they were OS threads, I
> > couldn't possibly manage it that way, even on a 2 or 4 processor
system.

>
> > At 10:48 AM 2/23/2007, you wrote:
> >>Reading this tread it seems it is missing the point. The issue with
> >>multithreading as implemented in Smalltalk is not performance,
> >>though more is always better, but the semantics. Semaphores and
> >>shared memory are too difficult to work with. What should be
> >>explored is how to add better, and by that I mean easier to work
> >>with semantics, for multithreading into Smalltalk. If Smalltalk
> >>provided a conceptually manageable way to manage even 100 threads we
> >>would be way ahead. I don't even think there are that many options:
> >>
> >>    * Transactional memory; this keeps shared memory but give better
> >> tools for managing conflicts.
> >>    * A pure Actor/CSP based notion of concurrency such as is used
in

> Erlang
> >>    * Hybrid approach where the normal message sends are single
> >> threaded but message sends to other threads have special semantics.
> >>
> >>I like option 3. This approach is a bit like the notion of using
> >>multiple images communication via Open Talk but they all happen to
> >>reside in the memory space sharing objects where possible.
> >>
> >>
> >>----------
> >>From: Travis Griggs [mailto:[hidden email]]
> >>Sent: February 22, 2007 7:13 PM
> >>To: VW NC
> >>Subject: Re: VisualWorks and support for native multi-threading
> >>
> >>On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
> >>
> >>
> >>[Grr, my reply last night went to Travis only.  Sorry Paul...]
> >>
> >>Travis is quite right.  The point to remember about multicore
> >>processors is that the chip still only has one interface to main
> >>memory and each core shares that interface (and the cache and
> >>(typically) TLBs) - remember many are socket-compatible with
> >>single-core processors.  If one has a memory-bound application
> >>throwing a multicore at it can do nothing to increase
> >>performance.  Large symbolic applications, a mainstay of server
> >>applications in OO languages, are such beasts.
> >>
> >>Whether this point is easy to enunciate against the marketing noise
> >>is, however, an entirely different question.
> >>
> >>The language of note that would seem to come closest to the notion
> >>of "don't worry about your threading" would be Erlang (I'm sure
> >>there are more noteworthy research languages, but I'm aware of known
> >>with any degree of popularity). The Erlang guys were recently
> >>excited about the ability to exploit multi cores. You can google for
> >>the results. One of the interesting sites I found was a SIP stack
> >>which had no coding changes made to it. When run on a quad core, it
> >>ran 1.8 times faster than the single core.
> >>
> >>--
> >>Travis Griggs
> >>Objologist
> >>One man's blue plane is another man's pink plane.
> >>
> >>
> >>
>
> > <Talk Small and Carry a Big Class Library>
> > James Robertson, Product Manager, Cincom Smalltalk
> > http://www.cincomsmalltalk.com/blog/blogView

Reply | Threaded
Open this post in threaded view
|

Re: VisualWorks and support for native multi-threading

Eliot Miranda-2
In reply to this post by Eliot Miranda-2


On 2/23/07, Paul Baumann <[hidden email]> wrote:
Hi Eliot,
 
I appreciate your reply to the post.
<a href="http://mlee888.wordpress.com/2006/03/31/java-performance-in-dual-coremultiprocessor-environment/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"> http://mlee888.wordpress.com/2006/03/31/java-performance-in-dual-coremultiprocessor-environment/

Well this poor soul has yet to realize that to a first approximation a 64-bit implementation of a symbolic program moves twice as much data as a 32-bit implementation and hence performance of memory-bound applications drops when moving to 64-bits (to a first approximation by a factor of two :) ).  I've talked about this before with the VW 64-bit application and how through using a revised object representation and immediate doubles I was able to restrict the slow-down to +15% on the x86-64.  You may get what you pay for, but with 64-bit computing you pay for what you get ;)
In reading your response I wondered if "memory-bound" is the key phrase. Does the problem go away if the 64-bit application has twice the memory? It seems there are hardware data movement costs that aren't intuitive. Is it not true that a 64-bit CPU moves twice the bits of a 32-bit CPU in the same clock cycle?


Its not to do with the amount of memry.  Its to do with the amount of memory traffic on and off chip.  The  chip-to-main-memory path is quite wide these days ( e.g. 16 bytes at a time) but it has a specific bandwidth.  A 32-bit application can read or write twice as many pointers through the same interface as a 64-bit one.  Now the on-chip-cache-to-register path is as wide as a register, so once one has a 64-bit value in cache on chip it should take no longer to copy 64-bits into a register than 32-bits into the half of the register being used to emulate a 32-bit processor.

So whether a 64-bit application is slower than a 32-bit applcation depends on how effective the on-chip cache is.  If the application fits entirely in the on-chip cache then the 64-bit app should run at the same speed as the 32-bit app.  But if the apps total size and access patterns are such that it doesn't fit in cache and substantial offchip memory traffic is required to accesss the data then the 64-bit app will start to slow down relative to thye 32-bit one.  Take an application that traverses a 1 gigapointer heap once.  The 32-bit app will read 4Gig in a time determined by the chip-to-main-memory bandwidth.  The 64-bit app will read 8Gig in twice the time.


The below looks like it could be cache cntention.  The two cores could be polluting each other's caches reducing the hit rate of te cache and increasing main memory traffic substantially.

HTH

Your post may be timely for a Java issue we are dealing with. The link I forwarded yesterday was in relation to that issue. A customer of ours reports experiencing 10X slowdown simply by going from a single-core to an Intel Core 2 Duo; here are the details:
 
We recently had an trader user make this comment:

Finally, I'm still seeing a 10x slowdown with multi-processors (I have an Intel Core 2 Duo).  To fix the problem, I change the process affinity to a single processor and it speeds up by 10x.  Someone, either at Sun or ICE has got to know how to fix this Java runtime problem.  I even tested the new Java build 1.5.0_10-b03 but the issue still exists.  It would be nice to have each trader lock on and run on a single processor to nearly double (or later quadruple) performance.

And then found this very interesting article …

Is it simply that the user needs to double the memory, or is there some unintuitive cost involved. The real problem we are trying to address may be different from the data size issues mentioned in the article, but I'll let you make that judgment. Do you know why Java would become so slow when the only (known) change was to use an Intel Core 2 Duo? I'm assuming a comparable clock speed between the processors, but I'll verify that.
 
Paul Baumann 
IntercontinentalExchange | ICE
2100 RiverEdge Pkwy | 5th Floor | Atlanta, GA 30328
Tel: 770.738.2137 | Fax: 770.951.1307 | Cel: 505.780.1470
[hidden email]

24-hour ice helpdesk 770.738.2101
<a title="http://www.theice.com/" style="color: rgb(51, 51, 51); text-decoration: none;" href="http://www.theice.com/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"> www.theice.com
 

 

 

 


This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.


Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: VisualWorks and support for native multi-threading

Eliot Miranda-2
In reply to this post by Michael Lucas-Smith


On 2/23/07, Michael Lucas-Smith <[hidden email]> wrote:
From what I'm hearing.. James Robertson is saying the easiest and most
approachable way to utilise multiple cores is to run multiple images.
At the time time, we have people pushing the Erlang model - which
enforces strict isolation of the threads.


I hope that's not what Jim is saying because it doesn't work for exactly the same reason it doesn't work with a multi-threaded VM, memory bandwidth.  Whether one expresses an algorithm in a single multi-threaded image or as a cluster of images if this algorithm gets run on a multi-core processor then the bottle neck is having a single interface from the processor to main memory.  If however the custer is a set of single-core machines one has more memory bandwidth because each processor has its own connection to main memory.

This matters because presumably the reason you're trying to go to multiple cores in the first place is performance.  But with multi-core unless each of your processes fit in 1/n of the cache (where n is the number of cores) the processes are going to contend for bandwidth, and in any case they'll collide in the cache unless its got a very fancy hash algorithm.


So we're actually talking about the same thing here. If the controls
to spawn off another running VM were internalized in Smalltalk -
sharing the same image base (perm space - does that work on 32bit VMs
too?) - then some light weight object-copy mechanism for sending
messages between the threads (STST could certainly be a good starting
point).

That combination would remove the complexity of managing multiple
images, because to make a new one you'd do something like newThread
:= ObjectMemory fork. There wouldn't be a giant memory overhead if
perm space were used by the image and we also pick up the same Erland
model as well as keeping our brilliant Smalltalk model.

Sounds great to me. And would it be that much harder to use than a
green thread (of which you can still utilise) .. not really. STST is
pretty easy to use. And given in this scenario you don't need to
"setup" STST (since it's all preconfigured for extrathread
communications), it really would be that simple.

As an added bonus, we'd also be able to do something Erlang cannot do
easily - pass by reference between our threads.

I'd say the only thing stopping this kind of capability ending up in
VW7.6 would be whether perm space memory sharing will work on 32bit
platforms?


Realistically there's only a chance of it working for the 64-bit implementation.  Making it work for 32-bits is tricky due to some low-level details to do with memory mapping addresses.  Both new segments and the permSpace pat of the image file use memory mapping but one wants permSpace to be the other side of a single boundary from non-permSpace.  In 64-bit and we can tag permSpace pointers so we no longer care where permSpace gets mapped.


Cheers,
Michael

> I think I'd have to answer this with "it depends".  In BottomFeeder,
> I spawn off N Smalltalk processes with each update cycle - each is an
> HTTP query of indeterminate duration, and each updates a discrete
> object.  I've not really had problems with this (beyond the VM
> blocking on DNS lookups, but that's unrelated).

> Now, having each of those threads be a Smalltalk process is pretty
> simple, and pretty easy to control.  If they were OS threads, I
> couldn't possibly manage it that way, even on a 2 or 4 processor system.

> At 10:48 AM 2/23/2007, you wrote:
>>Reading this tread it seems it is missing the point. The issue with
>>multithreading as implemented in Smalltalk is not performance,
>>though more is always better, but the semantics. Semaphores and
>>shared memory are too difficult to work with. What should be
>>explored is how to add better, and by that I mean easier to work
>>with semantics, for multithreading into Smalltalk. If Smalltalk
>>provided a conceptually manageable way to manage even 100 threads we
>>would be way ahead. I don't even think there are that many options:
>>
>>    * Transactional memory; this keeps shared memory but give better
>> tools for managing conflicts.
>>    * A pure Actor/CSP based notion of concurrency such as is used in Erlang
>>    * Hybrid approach where the normal message sends are single
>> threaded but message sends to other threads have special semantics.
>>
>>I like option 3. This approach is a bit like the notion of using
>>multiple images communication via Open Talk but they all happen to
>>reside in the memory space sharing objects where possible.
>>
>>
>>----------
>>From: Travis Griggs [mailto:[hidden email]]
>>Sent: February 22, 2007 7:13 PM
>>To: VW NC
>>Subject: Re: VisualWorks and support for native multi-threading
>>
>>On Feb 22, 2007, at 16:19, Eliot Miranda wrote:
>>
>>
>>[Grr, my reply last night went to Travis only.  Sorry Paul...]
>>
>>Travis is quite right.  The point to remember about multicore
>>processors is that the chip still only has one interface to main
>>memory and each core shares that interface (and the cache and
>>(typically) TLBs) - remember many are socket-compatible with
>>single-core processors.  If one has a memory-bound application
>>throwing a multicore at it can do nothing to increase
>>performance.  Large symbolic applications, a mainstay of server
>>applications in OO languages, are such beasts.
>>
>>Whether this point is easy to enunciate against the marketing noise
>>is, however, an entirely different question.
>>
>>The language of note that would seem to come closest to the notion
>>of "don't worry about your threading" would be Erlang (I'm sure
>>there are more noteworthy research languages, but I'm aware of known
>>with any degree of popularity). The Erlang guys were recently
>>excited about the ability to exploit multi cores. You can google for
>>the results. One of the interesting sites I found was a SIP stack
>>which had no coding changes made to it. When run on a quad core, it
>>ran 1.8 times faster than the single core.
>>
>>--
>>Travis Griggs
>>Objologist
>>One man's blue plane is another man's pink plane.
>>
>>
>>

> <Talk Small and Carry a Big Class Library>
> James Robertson, Product Manager, Cincom Smalltalk
> http://www.cincomsmalltalk.com/blog/blogView


Reply | Threaded
Open this post in threaded view
|

[7.4.1]Problem testing for isDirectory

Carl Gundel
In reply to this post by Travis Griggs-3
When testing the contents of a directory to collect the objects which
represent subdirectories I see:

   Unhandled exception: ERROR_FILE_NOT_FOUND ("advanced")

In this case advance is actually there (it's a directory).  The code I use
to see this error is:

| fn |
fn := 'c:\vw7.4.1' asFilename.
fn directoryContents select: [ :each | each asFilename isDirectory ]

I see something very similar if I specify 'c:\vw7.4.1\bin' as the folder but
instead it complains about README instead, which is a file.

So, here is the complete stack dump.

-Carl Gundel
http://www.libertybasic.com

Unhandled exception: ERROR_FILE_NOT_FOUND ("advanced")
FileErrorHolder class(OSErrorHolder class)>>reportProceedingOn:
FileErrorHolder(OSErrorHolder)>>reportErrorProceeding
optimized [] in OSErrorHolder class>>initializeErrorActions
SystemError>>handleErrorFor:
FATFilename(Filename)>>isDirectory
optimized [] in BasicProject class>>subDirectoriesFromPath:
Array(SequenceableCollection)>>select:
BasicProject class>>subDirectoriesFromPath:
UndefinedObject>>unboundMethod
UndefinedObject(Object)>>performMethod:arguments:
UndefinedObject(Object)>>performMethod:
TextEditorController(ParagraphEditor)>>evaluateCompiled:
optimized [] in ParagraphEditor>>evaluateSelection
BlockClosure>>ensure:
Cursor>>showWhile:
TextEditorController(ParagraphEditor)>>evaluateSelection
optimized [] in ParagraphEditor>>inspectIt
BlockClosure>>on:do:
TextEditorController(ParagraphEditor)>>inspectIt
WorkspacePage>>inspectIt
Workbook(AbstractWorkspace)>>smalltalkInspectIt
WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSymbol:
WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSelection:
optimized [] in [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
BlockClosure>>ensure:
optimized [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
BlockClosure>>on:do:
WinXPMenuBarButtonView(MenuBarButtonView)>>processShortcutKeyEventAsMenuItemAccessor:
[] in WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
OrderedCollection>>do:
WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
KeyboardProcessor>>processShortcutKeyEvent:
KeyboardProcessor>>processKeyboardEvent:
KeyboardProcessor>>processKeyboardEvent:for:
EventDispatcher>>dispatchEvent:
KeyPressedEvent(Event)>>dispatch
KeyPressedEvent(Event)>>dispatchForWindowManager:
optimized [] in WindowManager>>safelyDispatchForWindowManager:
BlockClosure>>on:do:
WindowManager>>safelyDispatchForWindowManager:
WindowManager>>processNextEvent
optimized [] in [] in WindowManager>>newProcess
BlockClosure>>on:do:
optimized [] in WindowManager>>newProcess
BlockClosure>>on:do:
optimized [] in Process class>>forBlock:priority:

----------------------------------------------------------------------
FileErrorHolder class(OSErrorHolder class)>>reportProceedingOn:
Receiver:
 a FileErrorHolder class
Instance Variables:
 superclass = OSErrorHolder
 methodDict = a MethodDictionary[3]
 format = 16386
 subclasses = nil
 instanceVariables = an Array[1]
 organization = ('accessing' #errorString #filename #filename:)

 name = #FileErrorHolder
 classPool = a NameSpaceOfClass[0]
 environment = a NameSpace[102]
Arguments:
 anErrorHolder = a FileErrorHolder(Error: ERROR_FILE_NOT_FOUND)
Temporaries:
 errorSignal = OSErrorHolder nonexistentSignal
Context PC = 31

----------------------------------------------------------------------
FileErrorHolder(OSErrorHolder)>>reportErrorProceeding
Receiver:
 a FileErrorHolder
Instance Variables:
 errorCode = 2
 filename = a FATFilename('advanced')
Context PC = 6

----------------------------------------------------------------------
optimized [] in OSErrorHolder class>>initializeErrorActions
Receiver:
 an UndefinedObject
Arguments:
 err = a SystemError(#'io error',2)
 arg = a FATFilename('advanced')
Context PC = 10

----------------------------------------------------------------------
SystemError>>handleErrorFor:
Receiver:
 a SystemError
Instance Variables:
 parameter = 2
 name = #'io error'
Arguments:
 contextInformation = a FATFilename('advanced')
Temporaries:
 errorBlock = BlockClosure [] in OSErrorHolder class>>initializeErrorActions
Context PC = 17

----------------------------------------------------------------------
FATFilename(Filename)>>isDirectory
Receiver:
 a FATFilename
Instance Variables:
 osName = a ByteArray[8]
 publicName = 'advanced'
 logicalName = nil
Temporaries:
 error = a SystemError(#'io error',2)
Context PC = 26

----------------------------------------------------------------------
optimized [] in BasicProject class>>subDirectoriesFromPath:
Receiver:
 an UndefinedObject
Arguments:
 each = 'advanced'
Context PC = 5

----------------------------------------------------------------------
Array(SequenceableCollection)>>select:
Receiver:
 an Array
Arguments:
 aBlock = BlockClosure [] in BasicProject class>>subDirectoriesFromPath:
Temporaries:
 aStream = a WriteStream
 index = 1
Context PC = 30

----------------------------------------------------------------------
BasicProject class>>subDirectoriesFromPath:
Receiver:
 a BasicProject class
Instance Variables:
 superclass = Object
 methodDict = a MethodDictionary[46]
 format = 16393
 subclasses = nil
 instanceVariables = an Array[9]
 organization = ('As yet unclassified' #addResource: #comment #comment:
#createFromCode:onError: #createNewVersion: #createNewVersion:comment:
#createOnError: #createXMLForWorkingVersion #createXMLMetadataFor:comment:
#defaultRemarks #deployPath #deployPath: #fromVersion #fromVersion:
#fromVersion:fromVersion: #fullPath #fullPath: #hasChanges #hasChanges:
#iconFullPath #iconFullPath: #initNamed: #initResources: #isVersioned #name
#name: #nextBranchVersionNumber #nextBranchVersionNumberFrom:
#nextVersionNumber #nextVersionNumberFrom: #path #proposedVersionNumber
#resources #resources: #resourcesXml #versionFullPath #versionMetadataPath
#versions #versionsPath #workingFile #workingFile: #workingVersionFullPath
#workingVersionMetadataFullPath #workingVersionNumber #xmlFor:comment:
#xmlForWorkingVersion)

 name = #BasicProject
 classPool = a NameSpaceOfClass[1]
 environment = nil
Arguments:
 aString = 'c:\vw7.4.1\'
Temporaries:
 dir = a FATFilename('c:\vw7.4.1')
Context PC = 10

----------------------------------------------------------------------
UndefinedObject>>unboundMethod
Receiver:
 an UndefinedObject
Context PC = 4

----------------------------------------------------------------------
UndefinedObject(Object)>>performMethod:arguments:
Receiver:
 an UndefinedObject
Arguments:
 method = AnnotatedMethod UndefinedObject>>unboundMethod
 args = an Array[0]
Context PC = 5

----------------------------------------------------------------------
UndefinedObject(Object)>>performMethod:
Receiver:
 an UndefinedObject
Arguments:
 method = AnnotatedMethod UndefinedObject>>unboundMethod
Context PC = 5

----------------------------------------------------------------------
TextEditorController(ParagraphEditor)>>evaluateCompiled:
Receiver:
 a TextEditorController
Instance Variables:
 model = a PluggableAdaptor
 view = a TextEditorView
 sensor = a TranslatingSensor
 menuHolder = a ValueHolder on: a Menu
 performer = a WorkspacePage
 beginTypeInIndex = nil
 anchorIndex = 1
 emphasisHere = nil
 dispatchTable = a DispatchTable
 charComposer = a CharacterComposer
 textHasChanged = true
 feelPolicy = a Win95FeelPolicy
 supportCodeEditingFeels = true
 localMenuItems = an Array[20]
 extendingDown = true
 keyboardProcessor = a KeyboardProcessor
 keyboardHook = nil
 readOnly = false
 accepted = false
 autoAccept = false
 continuousAccept = false
 tabMeansNextField = true
 tabRequiresControl = true
 dispatcher = an UIDispatcher
Arguments:
 aMethod = AnnotatedMethod UndefinedObject>>unboundMethod
Temporaries:
 context = nil
Context PC = 13

----------------------------------------------------------------------
optimized [] in ParagraphEditor>>evaluateSelection
Receiver:
 an UndefinedObject
Temporaries:
 .self = a TextEditorController
 .code = AnnotatedMethod UndefinedObject>>unboundMethod
Context PC = 7

----------------------------------------------------------------------
BlockClosure>>ensure:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in ParagraphEditor>>evaluateSelection
 outerContext = nil
 copiedValues = an Array[2]
Arguments:
 aBlock = BlockClosure [] in Cursor>>showWhile:
Temporaries:
 result = nil
Context PC = 4

----------------------------------------------------------------------
Cursor>>showWhile:
Receiver:
 a Cursor
Instance Variables:
 errorCode = 0
 handle = 4
 image = Depth1Image(extent: 16@16 depth: 1)
 mask = Depth1Image(extent: 16@16 depth: 1)
 hotSpot = 1@1
 name = 'xeq'
Arguments:
 aBlock = BlockClosure [] in ParagraphEditor>>evaluateSelection
Temporaries:
 oldcursor = Cursor normal
Context PC = 23

----------------------------------------------------------------------
TextEditorController(ParagraphEditor)>>evaluateSelection
Receiver:
 a TextEditorController
Instance Variables:
 model = a PluggableAdaptor
 view = a TextEditorView
 sensor = a TranslatingSensor
 menuHolder = a ValueHolder on: a Menu
 performer = a WorkspacePage
 beginTypeInIndex = nil
 anchorIndex = 1
 emphasisHere = nil
 dispatchTable = a DispatchTable
 charComposer = a CharacterComposer
 textHasChanged = true
 feelPolicy = a Win95FeelPolicy
 supportCodeEditingFeels = true
 localMenuItems = an Array[20]
 extendingDown = true
 keyboardProcessor = a KeyboardProcessor
 keyboardHook = nil
 readOnly = false
 accepted = false
 autoAccept = false
 continuousAccept = false
 tabMeansNextField = true
 tabRequiresControl = true
 dispatcher = an UIDispatcher
Temporaries:
 code = AnnotatedMethod UndefinedObject>>unboundMethod
 result = nil
Context PC = 14

----------------------------------------------------------------------
optimized [] in ParagraphEditor>>inspectIt
Receiver:
 an UndefinedObject
Temporaries:
 .self = a TextEditorController
Context PC = 6

----------------------------------------------------------------------
BlockClosure>>on:do:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in ParagraphEditor>>inspectIt
 outerContext = nil
 copiedValues = a TextEditorController
Arguments:
 anExceptionSelector = CompilationError
 handlerBlock = BlockClosure [] in ParagraphEditor>>inspectIt
Context PC = 18

----------------------------------------------------------------------
TextEditorController(ParagraphEditor)>>inspectIt
Receiver:
 a TextEditorController
Instance Variables:
 model = a PluggableAdaptor
 view = a TextEditorView
 sensor = a TranslatingSensor
 menuHolder = a ValueHolder on: a Menu
 performer = a WorkspacePage
 beginTypeInIndex = nil
 anchorIndex = 1
 emphasisHere = nil
 dispatchTable = a DispatchTable
 charComposer = a CharacterComposer
 textHasChanged = true
 feelPolicy = a Win95FeelPolicy
 supportCodeEditingFeels = true
 localMenuItems = an Array[20]
 extendingDown = true
 keyboardProcessor = a KeyboardProcessor
 keyboardHook = nil
 readOnly = false
 accepted = false
 autoAccept = false
 continuousAccept = false
 tabMeansNextField = true
 tabRequiresControl = true
 dispatcher = an UIDispatcher
Context PC = 20

----------------------------------------------------------------------
WorkspacePage>>inspectIt
Receiver:
 a WorkspacePage
Instance Variables:
 dependents = a PluggableAdaptor
 builder = an UIBuilder
 uiSession = nil
 eventHandlers = an IdentityDictionary[1]
 workspace = a Workbook
 label = 'Page 7'
 verboseLabel = nil
 filename = nil
 fileTimestamp = nil
 textModel = a PluggableAdaptor
 unacceptedText = nil
 savedSelection = nil
 savedFileTimestamp = nil
 textModelOverride = nil
Context PC = 5

----------------------------------------------------------------------
Workbook(AbstractWorkspace)>>smalltalkInspectIt
Receiver:
 a Workbook
Instance Variables:
 dependents = an ApplicationWindow 25
 builder = an UIBuilder
 uiSession = a ControlManager
 eventHandlers = nil
 locals = a WorkspaceVariablePool[10]
 importAll = true
 specificImports = an Array[3]
 importSummaryHolder = a ValueHolder on: 'All'
 pageExplanationHolder = a ValueHolder on: 'Text or Smalltalk code'
 statusBarVisible = true
 encodingChannel = a ValueHolder on: #Source
 menuBarHolder = a ValueHolder on: a Menu
 pageHolder = a SelectionInList
 lastInstalledPage = a WorkspacePage
Context PC = 5

----------------------------------------------------------------------
WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSymbol:
Receiver:
 a WinXPMenuBarButtonController
Instance Variables:
 model = nil
 view = a WinXPMenuBarButtonView
 sensor = a TranslatingSensor
 highlightOnOpen = false
Arguments:
 menuSelection = #smalltalkInspectIt
Context PC = 38

----------------------------------------------------------------------
WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSelection:
Receiver:
 a WinXPMenuBarButtonController
Instance Variables:
 model = nil
 view = a WinXPMenuBarButtonView
 sensor = a TranslatingSensor
 highlightOnOpen = false
Arguments:
 menuSelection = #smalltalkInspectIt
Context PC = 21

----------------------------------------------------------------------
optimized [] in [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
Receiver:
 an UndefinedObject
Temporaries:
 .self = a WinXPMenuBarButtonView
 .theValue = #smalltalkInspectIt
Context PC = 12

----------------------------------------------------------------------
BlockClosure>>ensure:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
 outerContext = nil
 copiedValues = an Array[2]
Arguments:
 aBlock = BlockClosure [] in [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
Temporaries:
 result = nil
Context PC = 4

----------------------------------------------------------------------
optimized [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
Receiver:
 an UndefinedObject
Temporaries:
 .self = a WinXPMenuBarButtonView
 .theValue = #smalltalkInspectIt
Context PC = 14

----------------------------------------------------------------------
BlockClosure>>on:do:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
 outerContext = nil
 copiedValues = an Array[2]
Arguments:
 anExceptionSelector = VetoAction
 handlerBlock = BlockClosure [] in
MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
Context PC = 18

----------------------------------------------------------------------
WinXPMenuBarButtonView(MenuBarButtonView)>>processShortcutKeyEventAsMenuItemAccessor:
Receiver:
 a WinXPMenuBarButtonView
Instance Variables:
 container = a BoundedWrapper on: a WinXPMenuBarButtonView
 eventHandlers = nil
 model = nil
 controller = a WinXPMenuBarButtonController
 properties = nil
 state = a WidgetState
 isInTransition = true
 latestValue = nil
 referenceValue = true
 label = Label for 'Smalltalk'
 textStyle = a VariableSizeTextAttributes
 helpText = nil
 menuHolder = a Menu
 menuBar = a WinXPMenuBar
 accessChar = 1
 flyingOver = false
Arguments:
 aKeyboardEvent = a KeyPressedEvent
Temporaries:
 theMenu = a Menu
 matchingMenuItem = a MenuItem 'Inspect it'
 theValue = #smalltalkInspectIt
 selector = nil
Context PC = 55

----------------------------------------------------------------------
[] in WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
Receiver:
 a WinXPMenuBar
Instance Variables:
 container = a MenuBarWrapper on: a WinXPMenuBar
 eventHandlers = nil
 components = an OrderedCollection[5]
 preferredBounds = 0@0 corner: 201@20
 leftSpace = 0
 spaceBetweenItems = 0
 extraSpaceTop = 0
 extraSpaceBottom = 0
 extraSpaceBetweenLines = 0
 menuChannel = a ValueHolder on: a Menu
 performer = a Workbook
 menuButtons = an OrderedCollection[5]
 nextMenuButton = nil
 lastMousePosition = 210@91
Arguments:
 each = a WinXPMenuBarButtonView
Temporaries:
 .aKeyboardEvent = a KeyPressedEvent
Context PC = 10

----------------------------------------------------------------------
OrderedCollection>>do:
Receiver:
 an OrderedCollection
Instance Variables:
 firstIndex = 1
 lastIndex = 5
Arguments:
 aBlock = BlockClosure [] in MenuBar>>processShortcutKeyEventInMenuBar:
Temporaries:
 index = 3
Context PC = 17

----------------------------------------------------------------------
WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
Receiver:
 a WinXPMenuBar
Instance Variables:
 container = a MenuBarWrapper on: a WinXPMenuBar
 eventHandlers = nil
 components = an OrderedCollection[5]
 preferredBounds = 0@0 corner: 201@20
 leftSpace = 0
 spaceBetweenItems = 0
 extraSpaceTop = 0
 extraSpaceBottom = 0
 extraSpaceBetweenLines = 0
 menuChannel = a ValueHolder on: a Menu
 performer = a Workbook
 menuButtons = an OrderedCollection[5]
 nextMenuButton = nil
 lastMousePosition = 210@91
Arguments:
 aKeyboardEvent = a KeyPressedEvent
Context PC = 20

----------------------------------------------------------------------
KeyboardProcessor>>processShortcutKeyEvent:
Receiver:
 a KeyboardProcessor
Instance Variables:
 keyboardConsumers = an OrderedCollection[2]
 currentConsumer = a TextEditorController
 default = nil
 cancel = nil
 keyboardHook = nil
 focusIsShifting = false
 currentConsumerChannel = nil
 acceptOnControlChange = false
 menuBar = a WinXPMenuBar
Arguments:
 aKeyEvent = a KeyPressedEvent
Temporaries:
 theCurrentConsumer = a TextEditorController
 index = nil
 controller = nil
Context PC = 28

----------------------------------------------------------------------
KeyboardProcessor>>processKeyboardEvent:
Receiver:
 a KeyboardProcessor
Instance Variables:
 keyboardConsumers = an OrderedCollection[2]
 currentConsumer = a TextEditorController
 default = nil
 cancel = nil
 keyboardHook = nil
 focusIsShifting = false
 currentConsumerChannel = nil
 acceptOnControlChange = false
 menuBar = a WinXPMenuBar
Arguments:
 aKeyboardEvent = a KeyPressedEvent
Temporaries:
 theCurrentConsumer = nil
Context PC = 8

----------------------------------------------------------------------
KeyboardProcessor>>processKeyboardEvent:for:
Receiver:
 a KeyboardProcessor
Instance Variables:
 keyboardConsumers = an OrderedCollection[2]
 currentConsumer = a TextEditorController
 default = nil
 cancel = nil
 keyboardHook = nil
 focusIsShifting = false
 currentConsumerChannel = nil
 acceptOnControlChange = false
 menuBar = a WinXPMenuBar
Arguments:
 keyboardEvent = a KeyPressedEvent
 aController = an ApplicationStandardSystemController
Temporaries:
 ev = a KeyPressedEvent
Context PC = 26

----------------------------------------------------------------------
EventDispatcher>>dispatchEvent:
Receiver:
 an EventDispatcher
Instance Variables:
 windowController = an ApplicationStandardSystemController
 currentMouseConsumer = nil
 grabbingMouse = false
 keyboardProcessor = a KeyboardProcessor
 lastControlObject = nil
 trapList = nil
 state = nil
 repairDamageWhenDebugging = true
 flushQueueAfterError = true
 distributeEventsWhenDebugging = true
 dragDropInProgress = false
 dragDropTracker = nil
 dispatchUnknownEvents = false
Arguments:
 event = a KeyPressedEvent
Temporaries:
 objectWantingControl = nil
 targetKeyboardProcessor = a KeyboardProcessor
Context PC = 82

----------------------------------------------------------------------
KeyPressedEvent(Event)>>dispatch
Receiver:
 a KeyPressedEvent
Instance Variables:
 time = nil
 initiator = an EventDispatcher
 window = an ApplicationWindow 25
 state = nil
 keyCharacter = $ "16r0011"
 metaState = 2
 alternativeKeyCharacter = nil
Context PC = 16

----------------------------------------------------------------------
KeyPressedEvent(Event)>>dispatchForWindowManager:
Receiver:
 a KeyPressedEvent
Instance Variables:
 time = nil
 initiator = an EventDispatcher
 window = an ApplicationWindow 25
 state = nil
 keyCharacter = $ "16r0011"
 metaState = 2
 alternativeKeyCharacter = nil
Arguments:
 aWinMgr = a WindowManager
Context PC = 4

----------------------------------------------------------------------
optimized [] in WindowManager>>safelyDispatchForWindowManager:
Receiver:
 an UndefinedObject
Temporaries:
 .event = a KeyPressedEvent
 .self = a WindowManager
Context PC = 6

----------------------------------------------------------------------
BlockClosure>>on:do:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in WindowManager>>safelyDispatchForWindowManager:
 outerContext = nil
 copiedValues = an Array[2]
Arguments:
 anExceptionSelector = BadControllerError
 handlerBlock = BlockClosure [] in
WindowManager>>safelyDispatchForWindowManager:
Context PC = 18

----------------------------------------------------------------------
WindowManager>>safelyDispatchForWindowManager:
Receiver:
 a WindowManager
Instance Variables:
 windows = an OrderedCollection[3]
 activeController = nil
 interruptLock = false
 outstandingMetaOrDamage = false
 openInProgress = false
 eventQueue = an EventQueue
 baseProcess = a Process in Semaphore>>wait
 dontFilterEvents = false
Arguments:
 event = a KeyPressedEvent
Context PC = 13

----------------------------------------------------------------------
WindowManager>>processNextEvent
Receiver:
 a WindowManager
Instance Variables:
 windows = an OrderedCollection[3]
 activeController = nil
 interruptLock = false
 outstandingMetaOrDamage = false
 openInProgress = false
 eventQueue = an EventQueue
 baseProcess = a Process in Semaphore>>wait
 dontFilterEvents = false
Temporaries:
 event = a KeyPressedEvent
Context PC = 9

----------------------------------------------------------------------
optimized [] in [] in WindowManager>>newProcess
Receiver:
 an UndefinedObject
Temporaries:
 .self = a WindowManager
Context PC = 13

----------------------------------------------------------------------
BlockClosure>>on:do:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in [] in WindowManager>>newProcess
 outerContext = nil
 copiedValues = a WindowManager
Arguments:
 anExceptionSelector = TerminateException
 handlerBlock = BlockClosure [] in [] in WindowManager>>newProcess
Context PC = 18

----------------------------------------------------------------------
optimized [] in WindowManager>>newProcess
Receiver:
 an UndefinedObject
Temporaries:
 .self = a WindowManager
Context PC = 15

----------------------------------------------------------------------
BlockClosure>>on:do:
Receiver:
 a BlockClosure
Instance Variables:
 method = CompiledBlock [] in WindowManager>>newProcess
 outerContext = nil
 copiedValues = a WindowManager
Arguments:
 anExceptionSelector = TerminateException
 handlerBlock = BlockClosure [] in [] in Process class>>forBlock:priority:
Context PC = 18

----------------------------------------------------------------------
optimized [] in Process class>>forBlock:priority:
Receiver:
 an UndefinedObject
Temporaries:
 .aBlock = BlockClosure [] in WindowManager>>newProcess
Context PC = 9


Reply | Threaded
Open this post in threaded view
|

Re: [7.4.1]Problem testing for isDirectory

Dennis smith-4
Well you in fact have two problems -- sort of.
1. the results of "directoryContents" is just the names, not the paths
so you need to build
       the path as  (c:\vw7.4.1' asFilename construct: each) -- then it
would exist and the test would return
       either true or false.
2. when doing isDirectory you should precede it with "exists"
       fn exists and: [fn isDirectory]
    since (for some strange reason) isDirectory blows up if the thing
does not exist -- which is the case you are seeing
    for the reason noted in #1 above.

Carl Gundel wrote:

> When testing the contents of a directory to collect the objects which
> represent subdirectories I see:
>
>   Unhandled exception: ERROR_FILE_NOT_FOUND ("advanced")
>
> In this case advance is actually there (it's a directory).  The code I
> use to see this error is:
>
> | fn |
> fn := 'c:\vw7.4.1' asFilename.
> fn directoryContents select: [ :each | each asFilename isDirectory ]
>
> I see something very similar if I specify 'c:\vw7.4.1\bin' as the
> folder but instead it complains about README instead, which is a file.
>
> So, here is the complete stack dump.
>
> -Carl Gundel
> http://www.libertybasic.com
>
> Unhandled exception: ERROR_FILE_NOT_FOUND ("advanced")
> FileErrorHolder class(OSErrorHolder class)>>reportProceedingOn:
> FileErrorHolder(OSErrorHolder)>>reportErrorProceeding
> optimized [] in OSErrorHolder class>>initializeErrorActions
> SystemError>>handleErrorFor:
> FATFilename(Filename)>>isDirectory
> optimized [] in BasicProject class>>subDirectoriesFromPath:
> Array(SequenceableCollection)>>select:
> BasicProject class>>subDirectoriesFromPath:
> UndefinedObject>>unboundMethod
> UndefinedObject(Object)>>performMethod:arguments:
> UndefinedObject(Object)>>performMethod:
> TextEditorController(ParagraphEditor)>>evaluateCompiled:
> optimized [] in ParagraphEditor>>evaluateSelection
> BlockClosure>>ensure:
> Cursor>>showWhile:
> TextEditorController(ParagraphEditor)>>evaluateSelection
> optimized [] in ParagraphEditor>>inspectIt
> BlockClosure>>on:do:
> TextEditorController(ParagraphEditor)>>inspectIt
> WorkspacePage>>inspectIt
> Workbook(AbstractWorkspace)>>smalltalkInspectIt
> WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSymbol:
>
> WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSelection:
>
> optimized [] in [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> BlockClosure>>ensure:
> optimized [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> BlockClosure>>on:do:
> WinXPMenuBarButtonView(MenuBarButtonView)>>processShortcutKeyEventAsMenuItemAccessor:
>
> [] in WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
> OrderedCollection>>do:
> WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
> KeyboardProcessor>>processShortcutKeyEvent:
> KeyboardProcessor>>processKeyboardEvent:
> KeyboardProcessor>>processKeyboardEvent:for:
> EventDispatcher>>dispatchEvent:
> KeyPressedEvent(Event)>>dispatch
> KeyPressedEvent(Event)>>dispatchForWindowManager:
> optimized [] in WindowManager>>safelyDispatchForWindowManager:
> BlockClosure>>on:do:
> WindowManager>>safelyDispatchForWindowManager:
> WindowManager>>processNextEvent
> optimized [] in [] in WindowManager>>newProcess
> BlockClosure>>on:do:
> optimized [] in WindowManager>>newProcess
> BlockClosure>>on:do:
> optimized [] in Process class>>forBlock:priority:
>
> ----------------------------------------------------------------------
> FileErrorHolder class(OSErrorHolder class)>>reportProceedingOn:
> Receiver:
> a FileErrorHolder class
> Instance Variables:
> superclass = OSErrorHolder
> methodDict = a MethodDictionary[3]
> format = 16386
> subclasses = nil
> instanceVariables = an Array[1]
> organization = ('accessing' #errorString #filename #filename:)
>
> name = #FileErrorHolder
> classPool = a NameSpaceOfClass[0]
> environment = a NameSpace[102]
> Arguments:
> anErrorHolder = a FileErrorHolder(Error: ERROR_FILE_NOT_FOUND)
> Temporaries:
> errorSignal = OSErrorHolder nonexistentSignal
> Context PC = 31
>
> ----------------------------------------------------------------------
> FileErrorHolder(OSErrorHolder)>>reportErrorProceeding
> Receiver:
> a FileErrorHolder
> Instance Variables:
> errorCode = 2
> filename = a FATFilename('advanced')
> Context PC = 6
>
> ----------------------------------------------------------------------
> optimized [] in OSErrorHolder class>>initializeErrorActions
> Receiver:
> an UndefinedObject
> Arguments:
> err = a SystemError(#'io error',2)
> arg = a FATFilename('advanced')
> Context PC = 10
>
> ----------------------------------------------------------------------
> SystemError>>handleErrorFor:
> Receiver:
> a SystemError
> Instance Variables:
> parameter = 2
> name = #'io error'
> Arguments:
> contextInformation = a FATFilename('advanced')
> Temporaries:
> errorBlock = BlockClosure [] in OSErrorHolder
> class>>initializeErrorActions
> Context PC = 17
>
> ----------------------------------------------------------------------
> FATFilename(Filename)>>isDirectory
> Receiver:
> a FATFilename
> Instance Variables:
> osName = a ByteArray[8]
> publicName = 'advanced'
> logicalName = nil
> Temporaries:
> error = a SystemError(#'io error',2)
> Context PC = 26
>
> ----------------------------------------------------------------------
> optimized [] in BasicProject class>>subDirectoriesFromPath:
> Receiver:
> an UndefinedObject
> Arguments:
> each = 'advanced'
> Context PC = 5
>
> ----------------------------------------------------------------------
> Array(SequenceableCollection)>>select:
> Receiver:
> an Array
> Arguments:
> aBlock = BlockClosure [] in BasicProject class>>subDirectoriesFromPath:
> Temporaries:
> aStream = a WriteStream
> index = 1
> Context PC = 30
>
> ----------------------------------------------------------------------
> BasicProject class>>subDirectoriesFromPath:
> Receiver:
> a BasicProject class
> Instance Variables:
> superclass = Object
> methodDict = a MethodDictionary[46]
> format = 16393
> subclasses = nil
> instanceVariables = an Array[9]
> organization = ('As yet unclassified' #addResource: #comment #comment:
> #createFromCode:onError: #createNewVersion: #createNewVersion:comment:
> #createOnError: #createXMLForWorkingVersion
> #createXMLMetadataFor:comment: #defaultRemarks #deployPath
> #deployPath: #fromVersion #fromVersion: #fromVersion:fromVersion:
> #fullPath #fullPath: #hasChanges #hasChanges: #iconFullPath
> #iconFullPath: #initNamed: #initResources: #isVersioned #name #name:
> #nextBranchVersionNumber #nextBranchVersionNumberFrom:
> #nextVersionNumber #nextVersionNumberFrom: #path
> #proposedVersionNumber #resources #resources: #resourcesXml
> #versionFullPath #versionMetadataPath #versions #versionsPath
> #workingFile #workingFile: #workingVersionFullPath
> #workingVersionMetadataFullPath #workingVersionNumber #xmlFor:comment:
> #xmlForWorkingVersion)
>
> name = #BasicProject
> classPool = a NameSpaceOfClass[1]
> environment = nil
> Arguments:
> aString = 'c:\vw7.4.1\'
> Temporaries:
> dir = a FATFilename('c:\vw7.4.1')
> Context PC = 10
>
> ----------------------------------------------------------------------
> UndefinedObject>>unboundMethod
> Receiver:
> an UndefinedObject
> Context PC = 4
>
> ----------------------------------------------------------------------
> UndefinedObject(Object)>>performMethod:arguments:
> Receiver:
> an UndefinedObject
> Arguments:
> method = AnnotatedMethod UndefinedObject>>unboundMethod
> args = an Array[0]
> Context PC = 5
>
> ----------------------------------------------------------------------
> UndefinedObject(Object)>>performMethod:
> Receiver:
> an UndefinedObject
> Arguments:
> method = AnnotatedMethod UndefinedObject>>unboundMethod
> Context PC = 5
>
> ----------------------------------------------------------------------
> TextEditorController(ParagraphEditor)>>evaluateCompiled:
> Receiver:
> a TextEditorController
> Instance Variables:
> model = a PluggableAdaptor
> view = a TextEditorView
> sensor = a TranslatingSensor
> menuHolder = a ValueHolder on: a Menu
> performer = a WorkspacePage
> beginTypeInIndex = nil
> anchorIndex = 1
> emphasisHere = nil
> dispatchTable = a DispatchTable
> charComposer = a CharacterComposer
> textHasChanged = true
> feelPolicy = a Win95FeelPolicy
> supportCodeEditingFeels = true
> localMenuItems = an Array[20]
> extendingDown = true
> keyboardProcessor = a KeyboardProcessor
> keyboardHook = nil
> readOnly = false
> accepted = false
> autoAccept = false
> continuousAccept = false
> tabMeansNextField = true
> tabRequiresControl = true
> dispatcher = an UIDispatcher
> Arguments:
> aMethod = AnnotatedMethod UndefinedObject>>unboundMethod
> Temporaries:
> context = nil
> Context PC = 13
>
> ----------------------------------------------------------------------
> optimized [] in ParagraphEditor>>evaluateSelection
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a TextEditorController
> .code = AnnotatedMethod UndefinedObject>>unboundMethod
> Context PC = 7
>
> ----------------------------------------------------------------------
> BlockClosure>>ensure:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in ParagraphEditor>>evaluateSelection
> outerContext = nil
> copiedValues = an Array[2]
> Arguments:
> aBlock = BlockClosure [] in Cursor>>showWhile:
> Temporaries:
> result = nil
> Context PC = 4
>
> ----------------------------------------------------------------------
> Cursor>>showWhile:
> Receiver:
> a Cursor
> Instance Variables:
> errorCode = 0
> handle = 4
> image = Depth1Image(extent: 16@16 depth: 1)
> mask = Depth1Image(extent: 16@16 depth: 1)
> hotSpot = 1@1
> name = 'xeq'
> Arguments:
> aBlock = BlockClosure [] in ParagraphEditor>>evaluateSelection
> Temporaries:
> oldcursor = Cursor normal
> Context PC = 23
>
> ----------------------------------------------------------------------
> TextEditorController(ParagraphEditor)>>evaluateSelection
> Receiver:
> a TextEditorController
> Instance Variables:
> model = a PluggableAdaptor
> view = a TextEditorView
> sensor = a TranslatingSensor
> menuHolder = a ValueHolder on: a Menu
> performer = a WorkspacePage
> beginTypeInIndex = nil
> anchorIndex = 1
> emphasisHere = nil
> dispatchTable = a DispatchTable
> charComposer = a CharacterComposer
> textHasChanged = true
> feelPolicy = a Win95FeelPolicy
> supportCodeEditingFeels = true
> localMenuItems = an Array[20]
> extendingDown = true
> keyboardProcessor = a KeyboardProcessor
> keyboardHook = nil
> readOnly = false
> accepted = false
> autoAccept = false
> continuousAccept = false
> tabMeansNextField = true
> tabRequiresControl = true
> dispatcher = an UIDispatcher
> Temporaries:
> code = AnnotatedMethod UndefinedObject>>unboundMethod
> result = nil
> Context PC = 14
>
> ----------------------------------------------------------------------
> optimized [] in ParagraphEditor>>inspectIt
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a TextEditorController
> Context PC = 6
>
> ----------------------------------------------------------------------
> BlockClosure>>on:do:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in ParagraphEditor>>inspectIt
> outerContext = nil
> copiedValues = a TextEditorController
> Arguments:
> anExceptionSelector = CompilationError
> handlerBlock = BlockClosure [] in ParagraphEditor>>inspectIt
> Context PC = 18
>
> ----------------------------------------------------------------------
> TextEditorController(ParagraphEditor)>>inspectIt
> Receiver:
> a TextEditorController
> Instance Variables:
> model = a PluggableAdaptor
> view = a TextEditorView
> sensor = a TranslatingSensor
> menuHolder = a ValueHolder on: a Menu
> performer = a WorkspacePage
> beginTypeInIndex = nil
> anchorIndex = 1
> emphasisHere = nil
> dispatchTable = a DispatchTable
> charComposer = a CharacterComposer
> textHasChanged = true
> feelPolicy = a Win95FeelPolicy
> supportCodeEditingFeels = true
> localMenuItems = an Array[20]
> extendingDown = true
> keyboardProcessor = a KeyboardProcessor
> keyboardHook = nil
> readOnly = false
> accepted = false
> autoAccept = false
> continuousAccept = false
> tabMeansNextField = true
> tabRequiresControl = true
> dispatcher = an UIDispatcher
> Context PC = 20
>
> ----------------------------------------------------------------------
> WorkspacePage>>inspectIt
> Receiver:
> a WorkspacePage
> Instance Variables:
> dependents = a PluggableAdaptor
> builder = an UIBuilder
> uiSession = nil
> eventHandlers = an IdentityDictionary[1]
> workspace = a Workbook
> label = 'Page 7'
> verboseLabel = nil
> filename = nil
> fileTimestamp = nil
> textModel = a PluggableAdaptor
> unacceptedText = nil
> savedSelection = nil
> savedFileTimestamp = nil
> textModelOverride = nil
> Context PC = 5
>
> ----------------------------------------------------------------------
> Workbook(AbstractWorkspace)>>smalltalkInspectIt
> Receiver:
> a Workbook
> Instance Variables:
> dependents = an ApplicationWindow 25
> builder = an UIBuilder
> uiSession = a ControlManager
> eventHandlers = nil
> locals = a WorkspaceVariablePool[10]
> importAll = true
> specificImports = an Array[3]
> importSummaryHolder = a ValueHolder on: 'All'
> pageExplanationHolder = a ValueHolder on: 'Text or Smalltalk code'
> statusBarVisible = true
> encodingChannel = a ValueHolder on: #Source
> menuBarHolder = a ValueHolder on: a Menu
> pageHolder = a SelectionInList
> lastInstalledPage = a WorkspacePage
> Context PC = 5
>
> ----------------------------------------------------------------------
> WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSymbol:
>
> Receiver:
> a WinXPMenuBarButtonController
> Instance Variables:
> model = nil
> view = a WinXPMenuBarButtonView
> sensor = a TranslatingSensor
> highlightOnOpen = false
> Arguments:
> menuSelection = #smalltalkInspectIt
> Context PC = 38
>
> ----------------------------------------------------------------------
> WinXPMenuBarButtonController(MenuBarButtonController)>>dispatchMenuSelection:
>
> Receiver:
> a WinXPMenuBarButtonController
> Instance Variables:
> model = nil
> view = a WinXPMenuBarButtonView
> sensor = a TranslatingSensor
> highlightOnOpen = false
> Arguments:
> menuSelection = #smalltalkInspectIt
> Context PC = 21
>
> ----------------------------------------------------------------------
> optimized [] in [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a WinXPMenuBarButtonView
> .theValue = #smalltalkInspectIt
> Context PC = 12
>
> ----------------------------------------------------------------------
> BlockClosure>>ensure:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> outerContext = nil
> copiedValues = an Array[2]
> Arguments:
> aBlock = BlockClosure [] in [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> Temporaries:
> result = nil
> Context PC = 4
>
> ----------------------------------------------------------------------
> optimized [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a WinXPMenuBarButtonView
> .theValue = #smalltalkInspectIt
> Context PC = 14
>
> ----------------------------------------------------------------------
> BlockClosure>>on:do:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> outerContext = nil
> copiedValues = an Array[2]
> Arguments:
> anExceptionSelector = VetoAction
> handlerBlock = BlockClosure [] in
> MenuBarButtonView>>processShortcutKeyEventAsMenuItemAccessor:
> Context PC = 18
>
> ----------------------------------------------------------------------
> WinXPMenuBarButtonView(MenuBarButtonView)>>processShortcutKeyEventAsMenuItemAccessor:
>
> Receiver:
> a WinXPMenuBarButtonView
> Instance Variables:
> container = a BoundedWrapper on: a WinXPMenuBarButtonView
> eventHandlers = nil
> model = nil
> controller = a WinXPMenuBarButtonController
> properties = nil
> state = a WidgetState
> isInTransition = true
> latestValue = nil
> referenceValue = true
> label = Label for 'Smalltalk'
> textStyle = a VariableSizeTextAttributes
> helpText = nil
> menuHolder = a Menu
> menuBar = a WinXPMenuBar
> accessChar = 1
> flyingOver = false
> Arguments:
> aKeyboardEvent = a KeyPressedEvent
> Temporaries:
> theMenu = a Menu
> matchingMenuItem = a MenuItem 'Inspect it'
> theValue = #smalltalkInspectIt
> selector = nil
> Context PC = 55
>
> ----------------------------------------------------------------------
> [] in WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
> Receiver:
> a WinXPMenuBar
> Instance Variables:
> container = a MenuBarWrapper on: a WinXPMenuBar
> eventHandlers = nil
> components = an OrderedCollection[5]
> preferredBounds = 0@0 corner: 201@20
> leftSpace = 0
> spaceBetweenItems = 0
> extraSpaceTop = 0
> extraSpaceBottom = 0
> extraSpaceBetweenLines = 0
> menuChannel = a ValueHolder on: a Menu
> performer = a Workbook
> menuButtons = an OrderedCollection[5]
> nextMenuButton = nil
> lastMousePosition = 210@91
> Arguments:
> each = a WinXPMenuBarButtonView
> Temporaries:
> .aKeyboardEvent = a KeyPressedEvent
> Context PC = 10
>
> ----------------------------------------------------------------------
> OrderedCollection>>do:
> Receiver:
> an OrderedCollection
> Instance Variables:
> firstIndex = 1
> lastIndex = 5
> Arguments:
> aBlock = BlockClosure [] in MenuBar>>processShortcutKeyEventInMenuBar:
> Temporaries:
> index = 3
> Context PC = 17
>
> ----------------------------------------------------------------------
> WinXPMenuBar(MenuBar)>>processShortcutKeyEventInMenuBar:
> Receiver:
> a WinXPMenuBar
> Instance Variables:
> container = a MenuBarWrapper on: a WinXPMenuBar
> eventHandlers = nil
> components = an OrderedCollection[5]
> preferredBounds = 0@0 corner: 201@20
> leftSpace = 0
> spaceBetweenItems = 0
> extraSpaceTop = 0
> extraSpaceBottom = 0
> extraSpaceBetweenLines = 0
> menuChannel = a ValueHolder on: a Menu
> performer = a Workbook
> menuButtons = an OrderedCollection[5]
> nextMenuButton = nil
> lastMousePosition = 210@91
> Arguments:
> aKeyboardEvent = a KeyPressedEvent
> Context PC = 20
>
> ----------------------------------------------------------------------
> KeyboardProcessor>>processShortcutKeyEvent:
> Receiver:
> a KeyboardProcessor
> Instance Variables:
> keyboardConsumers = an OrderedCollection[2]
> currentConsumer = a TextEditorController
> default = nil
> cancel = nil
> keyboardHook = nil
> focusIsShifting = false
> currentConsumerChannel = nil
> acceptOnControlChange = false
> menuBar = a WinXPMenuBar
> Arguments:
> aKeyEvent = a KeyPressedEvent
> Temporaries:
> theCurrentConsumer = a TextEditorController
> index = nil
> controller = nil
> Context PC = 28
>
> ----------------------------------------------------------------------
> KeyboardProcessor>>processKeyboardEvent:
> Receiver:
> a KeyboardProcessor
> Instance Variables:
> keyboardConsumers = an OrderedCollection[2]
> currentConsumer = a TextEditorController
> default = nil
> cancel = nil
> keyboardHook = nil
> focusIsShifting = false
> currentConsumerChannel = nil
> acceptOnControlChange = false
> menuBar = a WinXPMenuBar
> Arguments:
> aKeyboardEvent = a KeyPressedEvent
> Temporaries:
> theCurrentConsumer = nil
> Context PC = 8
>
> ----------------------------------------------------------------------
> KeyboardProcessor>>processKeyboardEvent:for:
> Receiver:
> a KeyboardProcessor
> Instance Variables:
> keyboardConsumers = an OrderedCollection[2]
> currentConsumer = a TextEditorController
> default = nil
> cancel = nil
> keyboardHook = nil
> focusIsShifting = false
> currentConsumerChannel = nil
> acceptOnControlChange = false
> menuBar = a WinXPMenuBar
> Arguments:
> keyboardEvent = a KeyPressedEvent
> aController = an ApplicationStandardSystemController
> Temporaries:
> ev = a KeyPressedEvent
> Context PC = 26
>
> ----------------------------------------------------------------------
> EventDispatcher>>dispatchEvent:
> Receiver:
> an EventDispatcher
> Instance Variables:
> windowController = an ApplicationStandardSystemController
> currentMouseConsumer = nil
> grabbingMouse = false
> keyboardProcessor = a KeyboardProcessor
> lastControlObject = nil
> trapList = nil
> state = nil
> repairDamageWhenDebugging = true
> flushQueueAfterError = true
> distributeEventsWhenDebugging = true
> dragDropInProgress = false
> dragDropTracker = nil
> dispatchUnknownEvents = false
> Arguments:
> event = a KeyPressedEvent
> Temporaries:
> objectWantingControl = nil
> targetKeyboardProcessor = a KeyboardProcessor
> Context PC = 82
>
> ----------------------------------------------------------------------
> KeyPressedEvent(Event)>>dispatch
> Receiver:
> a KeyPressedEvent
> Instance Variables:
> time = nil
> initiator = an EventDispatcher
> window = an ApplicationWindow 25
> state = nil
> keyCharacter = $ "16r0011"
> metaState = 2
> alternativeKeyCharacter = nil
> Context PC = 16
>
> ----------------------------------------------------------------------
> KeyPressedEvent(Event)>>dispatchForWindowManager:
> Receiver:
> a KeyPressedEvent
> Instance Variables:
> time = nil
> initiator = an EventDispatcher
> window = an ApplicationWindow 25
> state = nil
> keyCharacter = $ "16r0011"
> metaState = 2
> alternativeKeyCharacter = nil
> Arguments:
> aWinMgr = a WindowManager
> Context PC = 4
>
> ----------------------------------------------------------------------
> optimized [] in WindowManager>>safelyDispatchForWindowManager:
> Receiver:
> an UndefinedObject
> Temporaries:
> .event = a KeyPressedEvent
> .self = a WindowManager
> Context PC = 6
>
> ----------------------------------------------------------------------
> BlockClosure>>on:do:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in
> WindowManager>>safelyDispatchForWindowManager:
> outerContext = nil
> copiedValues = an Array[2]
> Arguments:
> anExceptionSelector = BadControllerError
> handlerBlock = BlockClosure [] in
> WindowManager>>safelyDispatchForWindowManager:
> Context PC = 18
>
> ----------------------------------------------------------------------
> WindowManager>>safelyDispatchForWindowManager:
> Receiver:
> a WindowManager
> Instance Variables:
> windows = an OrderedCollection[3]
> activeController = nil
> interruptLock = false
> outstandingMetaOrDamage = false
> openInProgress = false
> eventQueue = an EventQueue
> baseProcess = a Process in Semaphore>>wait
> dontFilterEvents = false
> Arguments:
> event = a KeyPressedEvent
> Context PC = 13
>
> ----------------------------------------------------------------------
> WindowManager>>processNextEvent
> Receiver:
> a WindowManager
> Instance Variables:
> windows = an OrderedCollection[3]
> activeController = nil
> interruptLock = false
> outstandingMetaOrDamage = false
> openInProgress = false
> eventQueue = an EventQueue
> baseProcess = a Process in Semaphore>>wait
> dontFilterEvents = false
> Temporaries:
> event = a KeyPressedEvent
> Context PC = 9
>
> ----------------------------------------------------------------------
> optimized [] in [] in WindowManager>>newProcess
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a WindowManager
> Context PC = 13
>
> ----------------------------------------------------------------------
> BlockClosure>>on:do:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in [] in WindowManager>>newProcess
> outerContext = nil
> copiedValues = a WindowManager
> Arguments:
> anExceptionSelector = TerminateException
> handlerBlock = BlockClosure [] in [] in WindowManager>>newProcess
> Context PC = 18
>
> ----------------------------------------------------------------------
> optimized [] in WindowManager>>newProcess
> Receiver:
> an UndefinedObject
> Temporaries:
> .self = a WindowManager
> Context PC = 15
>
> ----------------------------------------------------------------------
> BlockClosure>>on:do:
> Receiver:
> a BlockClosure
> Instance Variables:
> method = CompiledBlock [] in WindowManager>>newProcess
> outerContext = nil
> copiedValues = a WindowManager
> Arguments:
> anExceptionSelector = TerminateException
> handlerBlock = BlockClosure [] in [] in Process class>>forBlock:priority:
> Context PC = 18
>
> ----------------------------------------------------------------------
> optimized [] in Process class>>forBlock:priority:
> Receiver:
> an UndefinedObject
> Temporaries:
> .aBlock = BlockClosure [] in WindowManager>>newProcess
> Context PC = 9
>
>

--
Dennis Smith                         +1 416.798.7948
Cherniak Software Development Corporation   Fax: +1 416.798.0948
509-2001 Sheppard Avenue East        [hidden email]
Toronto, ON M2J 4Z8              sip:[hidden email]
Canada         http://www.CherniakSoftware.com
Entrance off Yorkland Blvd south of Sheppard Ave east of the DVP

Reply | Threaded
Open this post in threaded view
|

Re: [7.4.1]Problem testing for isDirectory

Dennis smith-4


Carl Gundel wrote:
>> Well you in fact have two problems -- sort of.
>> 1. the results of "directoryContents" is just the names, not the
>> paths so you need to build
>>       the path as  (c:\vw7.4.1' asFilename construct: each) -- then
>> it would exist and the test would return
>>       either true or false.
>
> Oh, that's a good point.  I admit I prefer VSE's way of doing it, with
> directory objects.
Not only does "directoryContents" NOT include the path, but the
"apparently" related
method
       filesMatching: -wild-card-string-
DOES include the path -- not so consistent.

We have our own wrapper on Filename's which adds a few methods which are
a bit more
consistent, and cleans up some things (like "isDirectory" if the item
does not exist).  Its not readily
exportable for others unfortunately as its tightly tied into Gemstone so
that our Gemstone file accesses
are the same and our client access to server files are the same etc
etc.  But it sure makes life easier.

>
>> 2. when doing isDirectory you should precede it with "exists"
>>       fn exists and: [fn isDirectory]
>>    since (for some strange reason) isDirectory blows up if the thing
>> does not exist -- which is the case you are seeing
>>    for the reason noted in #1 above.
>
> I'll take another stab at it.
>
> Thanks,
>
> -Carl Gundel
> http://www.libertybasic.com
>

--
Dennis Smith                         +1 416.798.7948
Cherniak Software Development Corporation   Fax: +1 416.798.0948
509-2001 Sheppard Avenue East        [hidden email]
Toronto, ON M2J 4Z8              sip:[hidden email]
Canada         http://www.CherniakSoftware.com
Entrance off Yorkland Blvd south of Sheppard Ave east of the DVP

12