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. |
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 > 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. |
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 |
In reply to this post by Paul Baumann
On 2/22/07, Paul Baumann <[hidden email]> wrote:
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 ;)
|
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 |
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 |
> -----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 > > 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 > 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 |
In reply to this post by Eliot Miranda-2
On 2/23/07, Paul Baumann <[hidden email]> wrote:
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
|
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 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 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, |
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 |
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 |
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 |
Free forum by Nabble | Edit this page |