digitalmars.D - Sharing in D
- Walter Bright (1/1) Jul 30 2008 http://www.reddit.com/comments/6u7k0/sharing_in_d/
- Robert Fraser (9/10) Jul 30 2008 WANT. It would be very useful for certain applications. However, I'm
- bearophile (6/9) Jul 31 2008 This requires to be careful using global variables, because you may need...
- Robert Fraser (3/8) Jul 31 2008 I was talking UX wise. I don't want to have to think whether my variable...
- Walter Bright (3/5) Jul 31 2008 I've already worked out the implementation issues of transitivity, so I
- JAnderson (13/14) Jul 30 2008 I like this proposal. Maybe the shared option could be in the typical
- Steven Schveighoffer (16/17) Jul 30 2008 There are 2 problems I see with this scheme.
- Walter Bright (19/39) Jul 30 2008 Nearly all global data is assumed to be and treated as if it were
- downs (6/20) Jul 31 2008 Since when is it the language's job to tell us what's acceptable and wha...
- Walter Bright (20/39) Jul 31 2008 A couple years ago, I was in a room with 30 of the top C++ programmers
- downs (7/55) Jul 31 2008 Point taken, taken and taken.
- Walter Bright (6/10) Jul 31 2008 The idea is to no longer allow unsynchronized uncontrolled sharing of
- downs (2/12) Jul 31 2008 Yeah, but I'd like a way to do it that doesn't leave me entirely on my o...
- Walter Bright (2/16) Jul 31 2008 I don't understand what you're asking for.
- downs (6/23) Aug 01 2008 Sorry.
- Walter Bright (2/14) Aug 01 2008 Sorry, I still have no idea what you're asking for.
- downs (8/23) Aug 01 2008 Okay.
- Sean Kelly (30/51) Aug 01 2008 "shared".
- JAnderson (13/67) Aug 02 2008 Some good points.
- Don (2/46) Aug 14 2008 Would this be an end to 'static' variables?
- Sean Kelly (10/65) Aug 14 2008 I think that's the only feasible option for D1, which is why I'm
- Helmut Leitner (11/37) Jul 31 2008 Perhaps this has already been discussed, but there seems another
- Koroskin Denis (14/47) Jul 31 2008 Other system to take into an account is Playstation 3. It has 7 cores, i...
- Helmut Leitner (12/16) Jul 31 2008 All NVIDIA graphics boards from 8400 up are usable
- bearophile (8/9) Jul 31 2008 And it's working fast as hell already, I have tried CUDA some on my GPU ...
- Kyle Furlong (3/43) Jul 31 2008 This is a library realm topic, given the ability to mixin optimal code
- Kyle Furlong (2/46) Jul 31 2008 I spoke too soon, this would require asm support for those processors.
- Sean Kelly (36/70) Jul 31 2008 In my opinion, the easiest way to describe the hardware side of things i...
- Walter Bright (13/48) Jul 31 2008 D will eliminate implicit data sharing. To share data, you'll have to
- Sean Kelly (20/68) Jul 31 2008 But volatile in Java is completely different. And Java doesn't support ...
- superdan (2/8) Jul 31 2008 haven't read bartosz' stuff yet, so no comment on that. but with all due...
- Walter Bright (15/32) Jul 31 2008 From talking to people who do large scale multithreaded Java programs,
- superdan (6/27) Jul 31 2008 yech. so i write this:
- Walter Bright (3/14) Jul 31 2008 If conventional code were generated for i++, and i was accessed from
- superdan (2/18) Jul 31 2008 i grok that. my problem is that your shared doesn't help me with writing...
- Walter Bright (7/10) Aug 01 2008 Actually, the current plan is that ++ would be disabled for shared
- Sean Kelly (8/18) Aug 01 2008 A totally worthwhile tradeoff IMO. The alternative would be to
-
Walter Bright
(6/15)
Aug 01 2008
I'm surprised, we expected much more flak about that
. The idea is to... - Sean Kelly (4/18) Aug 01 2008 Not necessarily. If i is a 32-bit number and only one thread is
- superdan (2/23) Aug 01 2008 i don't think so. reading must be still fenced if at least one thread wr...
- Sean Kelly (14/35) Aug 01 2008 it. walt is correct.
- superdan (2/37) Aug 01 2008 makes sense. but i guess we agree that that is the rare case in which yo...
- Walter Bright (4/8) Aug 01 2008 It's not just me. There are several people who've been hammering away at...
- Walter Bright (4/10) Aug 01 2008 If you've got only one thread, why is it shared ? If it is shared,
- superdan (2/13) Aug 01 2008 i think he means a different case. you have many threads alright. but on...
- Walter Bright (7/22) Aug 01 2008 If Sean means that the code is synchronized so only one thread has
- Sean Kelly (7/17) Aug 01 2008 Only one writer, multiple readers. But this is assuming the INC is issu...
- Sean Kelly (43/75) Jul 31 2008 That's the problem with providing such fundamental support for lock-free
- superdan (8/88) Jul 31 2008 fraid you might have a slightly specialized definition of what lock-free...
- Walter Bright (2/19) Aug 01 2008 Yes.
- Sean Kelly (23/50) Aug 01 2008 synchronize through atomic assignments.
- Walter Bright (3/8) Aug 02 2008 You're right, it won't always be optimal. The idea is to get it right
- Walter Bright (9/47) Jul 31 2008 But that is useless for multithreading, because Java and C++ types have
- superdan (2/24) Jul 31 2008 i'm afraid c++ and c++0x and java are "actually fine" to write multiproc...
- Sean Kelly (14/38) Jul 31 2008 code if the coder is fucking superman on steroids after an overdose of r...
- Walter Bright (18/21) Jul 31 2008 There's also the issue of the person who thinks they know how to write
- bearophile (4/5) Jul 31 2008 Java is some years old, while Scala is a new language that runs on the J...
- Leandro Lucarella (10/22) Jul 31 2008 Tell that to singleton-monkeys =P
- Walter Bright (3/4) Jul 31 2008 Yeah, and singletons suffer from the double-checked locking bug! Bartosz...
- Steven Schveighoffer (33/71) Jul 31 2008 I have no idea where you came up with this. To me global means shared.
- Walter Bright (32/75) Jul 31 2008 The idea is that encapsulation is better, and having something shared
- Steven Schveighoffer (54/120) Aug 01 2008 So if I write:
- Sean Kelly (10/41) Aug 01 2008 I'm hoping that 'shared' will force programmers to think about what they...
- Steven Schveighoffer (10/67) Aug 01 2008 I'm thinking more in the case of functions. If I have a function foo, a...
- Sean Kelly (6/73) Aug 01 2008 Darnit, you're right. That's just like 'volatile' in C++. In fact,
- superdan (11/79) Aug 01 2008 sounds interesting but i don't get it. we have:
- Sean Kelly (9/14) Aug 01 2008 this is intriguing shit. unification is power.
- BCS (4/8) Aug 01 2008 The only useful middle ground I see is covered by shared + const (one th...
- Steven Schveighoffer (19/44) Aug 01 2008 The issue I see is that it's not as simple as flipping a switch. If I w...
- superdan (17/159) Aug 01 2008 i dun think so. first off it's naive to assume that global == shared. no...
- Sean Kelly (5/30) Aug 01 2008 That, or 'shared' applies only to the pointer, not to the value being po...
- Sean Kelly (5/34) Aug 01 2008 Err... I spoke too soon. Not a problem because then the
- Walter Bright (6/12) Aug 01 2008 I think you put your finger on the problem. The default behavior of C++
- Dee Girl (2/21) Aug 01 2008 Agree with Steve. There should not be easy casting of pointers. i think ...
- JAnderson (22/27) Jul 31 2008 compiler has no idea whether I'm going to change it in another thread.
- Steven Schveighoffer (10/28) Aug 01 2008 I believe the direction that this is heading is promising, but my concer...
- superdan (2/94) Jul 31 2008 you may as well be equally right. or even more right, as you usually are...
- Steven Schveighoffer (10/20) Aug 01 2008 Just because I'm not published all over google doesn't mean I don't know...
- superdan (8/33) Aug 01 2008 thanks for keeping ur cool. really appreciate that. my intent was not to...
- Steven Schveighoffer (25/71) Aug 01 2008 I probably have more hits under schveiguy than Steven Schveighoffer.
- superdan (9/81) Aug 01 2008 and you're implying that it can't be done any better. you know, if every...
- Walter Bright (4/11) Aug 01 2008 Do you believe that General McAuliffe really said "nuts" at the Battle
- superdan (3/15) Aug 01 2008 let's see. four-words expletive too strong for the american public. sure...
- Walter Bright (3/10) Aug 01 2008 My father met the man and asked him. The actual word rhymes with "spit"....
- Steven Schveighoffer (29/93) Aug 01 2008 I'm not saying that we shouldn't try. I'm just saying it *might* be
-
JAnderson
(14/27)
Jul 31 2008
- Steven Schveighoffer (22/41) Jul 31 2008 So should people wait to write libraries until all this is fleshed out? ...
- Sean Kelly (16/32) Jul 31 2008 libd forked the language and is far better for it. Tango has avoided th...
- bearophile (7/11) Jul 31 2008 I think D is already partially unfit for being a system language, the ru...
- Sean Kelly (25/34) Jul 31 2008 Agreed. This is largely related to the generated TypeInfo, and is somew...
- superdan (2/9) Jul 31 2008 i agree. std.algorithm i sleep with under my pillow. but std.xml. what a...
- downs (5/16) Aug 01 2008 Heh. Want to have some fun, take a look at std.zip.
- Walter Bright (2/13) Aug 01 2008 Please file this with bugzilla, or even better, a patch!
- bearophile (6/8) Jul 31 2008 I agree, in many D programs I have found that avoiding memory allocation...
- Walter Bright (11/18) Jul 31 2008 I wrote a version of Empire (the game) in D that does no allocation at
- dsimcha (28/38) Jul 31 2008 memory footprint is large; here it's compared with Free Pascal:
- downs (3/6) Jul 31 2008 Couldn't agree more.
- bearophile (5/11) Jul 31 2008 I too use D mostly for bioinformatics, I have introduced it (with Python...
- Steven Schveighoffer (10/17) Aug 01 2008 After thinking about this some more, I realize that this part of my argu...
- Knud Soerensen (4/5) Jul 30 2008 I have also posted it on my new news site http://crowdnews.eu
- Craig Black (7/7) Jul 31 2008 If I understand it correctly, then you are going down the right path wit...
- Walter Bright (4/10) Jul 31 2008 Of course - casting a shared type to unshared means subverting any
- superdan (3/9) Jul 31 2008 yeh i could swear i read an article about that. was his name grosh or so...
- Sean Kelly (33/34) Jul 31 2008 Sounds like the addition of a thread-local storage class (which
- Walter Bright (8/23) Jul 31 2008 It's actually implemented in D 2.0 as the __thread storage class,
- Sean Kelly (14/26) Jul 31 2008 What about this:
- downs (4/12) Aug 01 2008 1.0 has tools.threads' TLS!(), so you can use that :) It works under win...
- Jarrett Billingsley (4/17) Aug 01 2008 You do realize (1) you're advertising to one of the main Tango devs, and...
- downs (4/25) Aug 01 2008 Um.
- Walter Bright (3/17) Aug 01 2008 Shared cannot be implicitly cast to unshared. Just like const cannot be
- Russell Lewis (2/4) Aug 07 2008 But you can implicitly cast unshared to shared, right?
- Steven Schveighoffer (5/9) Aug 07 2008 No. There is no implicit casting or else you can have data that is shar...
- Russell Lewis (4/13) Aug 07 2008 Yeah, I saw your (was it you?) example of how that would become
- Steven Schveighoffer (13/26) Aug 08 2008 I think there may be no middle ground, as in order for locks to work, ev...
- Russell Lewis (17/29) Aug 08 2008 I think that you misunderstood my locking idea. My idea was that there
- Koroskin Denis (3/4) Jul 31 2008 Hello, volatile! :)
- Jason House (3/4) Jul 31 2008 This is one of my 3 big wishes for the D language.
- Walter Bright (4/14) Jul 31 2008 Pure doesn't apply to data types, it applies to functions. I don't know
- superdan (4/20) Jul 31 2008 99% of the global shit i ever defined i wanted to be thread local. i had...
- downs (4/26) Aug 01 2008 What about cases that depend on external resources, like a global buffer...
- Sean Kelly (15/40) Aug 01 2008 communicate across threads is sheer suicide.
- Jesse Phillips (10/11) Jul 31 2008 I haven't done much threading, so this sounds mostly good. On question I...
- Walter Bright (2/6) Jul 31 2008 Unshared can be implicitly cast to shared, so you shouldn't have to.
- Jason House (5/6) Aug 01 2008 That should not be implicit.
- Walter Bright (5/17) Aug 01 2008 True, but the memory allocation system shouldn't be (and isn't) built
- Jason House (4/17) Aug 01 2008 Let's say I have an object that was originally written assuming non-shar...
- Steven Schveighoffer (11/36) Aug 01 2008 I have a feeling that the shared/unshared comes with a requriement for
- Jason House (2/48) Aug 01 2008 I'd much prefer to discuss the problematic use case and either confirmin...
- Walter Bright (2/5) Aug 01 2008 That's right. Shared objects can only call shared or synchronized method...
- Jason House (3/24) Aug 01 2008 I don't see how having one thread with a reference to unshared data and ...
- Sean Kelly (20/35) Aug 01 2008 the single-threaded garbage collection would only scan memory for the th...
- JAnderson (4/42) Aug 02 2008 My thought was you could use Ref counting for shared memory and mark and...
- Jason House (3/5) Aug 02 2008 That's a really good idea. Mark and sweep (as currently implemented in D...
- JAnderson (24/30) Aug 02 2008 Thanks,
- Walter Bright (3/11) Aug 01 2008 Shared unifies shared and unshared.
- Steven Schveighoffer (31/43) Aug 01 2008 I'm assuming you read my previous example, but I'll rewrite it to
- Jason House (2/56) Aug 01 2008 Uh oh Steve, you're starting to sound like me! I made the 2^n comment in...
- Walter Bright (3/9) Aug 01 2008 Eh, I think you've got me there. Looks like unshared cannot be
- Bruno Medeiros (5/16) Aug 11 2008 Akin to why const cannot be implicitly converted to invariant, no?
- dsimcha (10/10) Aug 11 2008 One thing that recently popped into my mind about the shared/unshared di...
- bearophile (4/7) Aug 11 2008 If you take a slice of an array [a..b] you don't copy data, so if thread...
- Sean Kelly (9/19) Aug 11 2008 For arrays with elements smaller than the bus width or for unaligned arr...
- mort (2/3) Aug 01 2008 It seems that you want the semantics for shared to be ``allocated on eit...
- Jason House (2/3) Aug 04 2008 When can we expect to see this in D2? For the first time since moving to...
- Walter Bright (2/3) Aug 04 2008 It'll come in stages. For example, D 2.0 already supports thread local s...
http://www.reddit.com/comments/6u7k0/sharing_in_d/
Jul 30 2008
Walter Bright Wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/WANT. It would be very useful for certain applications. However, I'm worried that this may perhaps add even more complexity to an already stretched type system. How about making the less safe alternative (shared/unchecked) the default (so current programs keep working the way they already do) and people who want the additional compelxity and overhead use unshared explicitly (just as const/invariant is not the default and people need to explicitly say that).
Jul 30 2008
Bartosz Milewski:This requires that all objects, by default, be thread local. For instance, if you declare a global object and initialize it in one thread, another thread will see a different version of this object.<This requires to be careful using global variables, because you may need lot of memory. On the other hand, each L1 cache can keep such objects safely, with little need of copying such data to other L1 caches. Robert Fraser:However, I'm worried that this may perhaps add even more complexity to an already stretched type system.If the type system is able to manage the transitive immutability, then it can manage this too, I think. The things that are going to stress the type system of D are different ones, I think; for example see the thread about nested templates, where the best solution proposed was to use an union to punch a hole in it. Bye, bearophile
Jul 31 2008
bearophile Wrote:Robert Fraser:I was talking UX wise. I don't want to have to think whether my variable is a shared(atomic(const(int)*)[]).However, I'm worried that this may perhaps add even more complexity to an already stretched type system.If the type system is able to manage the transitive immutability, then it can manage this too, I think. The things that are going to stress the type system of D are different ones, I think; for example see the thread about nested templates, where the best solution proposed was to use an union to punch a hole in it.
Jul 31 2008
bearophile wrote:If the type system is able to manage the transitive immutability, then it can manage this too, I think.I've already worked out the implementation issues of transitivity, so I can easily leverage that code for the sharing transitivity.
Jul 31 2008
Walter Bright wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/I like this proposal. Maybe the shared option could be in the typical bracket notation that D is so fond off: shared { Object X; //Shared object class Foo() {} //Shared class for any object that uses this / Shared members class Bar() {} } That way the few people that are passing non-shared objects around can simply put everything into a shared block, simplifying migration. -Joel
Jul 30 2008
"Walter Bright" wrotehttp://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data. I would hazard to guess that adopting this would cause a larger rift than const. Second, the fact that you can't implicitly cast shared to unshared and vice versa. It's going to make communication between both 'worlds' very error prone, as you will be required to cast for any call from one to the other. People will do this just to get their code to work, without thinking about the consequences. Even those that do think about the consequences, can't have the compiler statically check the cast in either direction, so once you cast, you lose all the benefit. I'd have to see solutions to these before I'd think it was a good idea. Or else examples of how to avoid these problems. -Steve
Jul 30 2008
Steven Schveighoffer wrote:"Walter Bright" wroteNearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data.I would hazard to guess that adopting this would cause a larger rift than const.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Second, the fact that you can't implicitly cast shared to unshared and vice versa. It's going to make communication between both 'worlds' very error prone, as you will be required to cast for any call from one to the other.I think the reverse is true. Moving data between those worlds is dangerous and needs to be carefully vetted, so requiring an explicit cast will reduce the chance of this happening unintentionally.People will do this just to get their code to work, without thinking about the consequences.True, but having it happen implicitly is even worse, because there's no indication that it is happening.Even those that do think about the consequences, can't have the compiler statically check the cast in either direction, so once you cast, you lose all the benefit.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.I'd have to see solutions to these before I'd think it was a good idea. Or else examples of how to avoid these problems.
Jul 30 2008
Walter Bright wrote:Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Since when is it the language's job to tell us what's acceptable and what's not?But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.The double checked locking "bug" is only a bug on certain architectures, none of which D is supported on. What's the point here again? --downs
Jul 31 2008
downs wrote:Walter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.I meant that programmers will no longer find the language acceptable if it doesn't offer better support.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Since when is it the language's job to tell us what's acceptable and what's not?D is not only meant to be more than an x86 only language, the x86 family steadily moves towards the relaxed sequential consistency model. The threading model supported by Java and the upcoming C++0x release are both based on the relaxed model, that is clearly where the industry expects things to go, and I see no reason to believe otherwise.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.The double checked locking "bug" is only a bug on certain architectures, none of which D is supported on.
Jul 31 2008
Walter Bright wrote:downs wrote:Point taken, taken and taken. If this can be done well, I believe it may become a significant advantage for the language. IMHO, however, most global variables are intended to be instantiated only once, not once per thread. Because of this, the success of this model hinges on how easy an object can be transferred between threads. Some sort of language enforced blocking, maybe? I.e. if you mark an object as unique, as in, "unique Class foo", it is implicitly shared, but *treated as if it were nonshared*, as threads need to acquire a sync lock before accessing the object, and references to the object or its members cannot leave the sync block. Delegates would be a special case: they can leave the sync lock, as long as any "this" access inside them is itself synchronized. --downsWalter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.I meant that programmers will no longer find the language acceptable if it doesn't offer better support.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Since when is it the language's job to tell us what's acceptable and what's not?D is not only meant to be more than an x86 only language, the x86 family steadily moves towards the relaxed sequential consistency model. The threading model supported by Java and the upcoming C++0x release are both based on the relaxed model, that is clearly where the industry expects things to go, and I see no reason to believe otherwise.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.The double checked locking "bug" is only a bug on certain architectures, none of which D is supported on.
Jul 31 2008
downs wrote:IMHO, however, most global variables are intended to be instantiated only once, not once per thread. Because of this, the success of this model hinges on how easy an object can be transferred between threads. Some sort of language enforced blocking, maybe?The idea is to no longer allow unsynchronized uncontrolled sharing of data between threads as the *default* behavior. If you want to do it, you'll have to do it *intentionally*. Note that invariant data will be implicitly shared because it does not need synchronization or fencing.
Jul 31 2008
Walter Bright wrote:downs wrote:Yeah, but I'd like a way to do it that doesn't leave me entirely on my own, considering that it's imho a common use-case.IMHO, however, most global variables are intended to be instantiated only once, not once per thread. Because of this, the success of this model hinges on how easy an object can be transferred between threads. Some sort of language enforced blocking, maybe?The idea is to no longer allow unsynchronized uncontrolled sharing of data between threads as the *default* behavior. If you want to do it, you'll have to do it *intentionally*.
Jul 31 2008
downs wrote:Walter Bright wrote:I don't understand what you're asking for.downs wrote:Yeah, but I'd like a way to do it that doesn't leave me entirely on my own, considering that it's imho a common use-case.IMHO, however, most global variables are intended to be instantiated only once, not once per thread. Because of this, the success of this model hinges on how easy an object can be transferred between threads. Some sort of language enforced blocking, maybe?The idea is to no longer allow unsynchronized uncontrolled sharing of data between threads as the *default* behavior. If you want to do it, you'll have to do it *intentionally*.
Jul 31 2008
Walter Bright wrote:downs wrote:Sorry. I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Walter Bright wrote:I don't understand what you're asking for.downs wrote:Yeah, but I'd like a way to do it that doesn't leave me entirely on my own, considering that it's imho a common use-case.IMHO, however, most global variables are intended to be instantiated only once, not once per thread. Because of this, the success of this model hinges on how easy an object can be transferred between threads. Some sort of language enforced blocking, maybe?The idea is to no longer allow unsynchronized uncontrolled sharing of data between threads as the *default* behavior. If you want to do it, you'll have to do it *intentionally*.
Aug 01 2008
downs wrote:I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.
Aug 01 2008
Walter Bright wrote:downs wrote:Okay. In the current system, every object "belongs" to every thread equally - synchronization blocks are used to prevent interference. In the new system, this behavior, if I understand correctly, is equivalent to "shared". The default, non-shared, would be objects that belong, permanently, to exactly one thread - the one that created them, to the extent that accessing them from another thread would constitute a compiler failure. What I am looking for, then, is to somehow temporarily, or permanently, change the thread that a specific instance belongs to, transfer ownership to another thread, so to speak, in an atomic manner - so that at no time more than one thread possesses ownership of the object - thus gaining, basically, the guaranteed thread-safety of a non-shared object with the convenience of a shared object. So it's basically a form of forced "synchronized" blocks - a thread that would try to access such an "unique" object, would first have to acquire ownership of it, to prevent threading issues - an action similar to the current "synchronized(this)". In fact, every access to an unique object would come down to an implicit "synchronized(obj)", which would allow us to treat the object as if it _were_ thread-local for the purpose of that access, because even though it isn't, no other thread could interfere with it. Hope that clears things up :/I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.
Aug 01 2008
== Quote from downs (default_357-line yahoo.de)'s articleWalter Bright wrote:synchronization blocks are used to prevent interference.downs wrote:Okay. In the current system, every object "belongs" to every thread equally -I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.In the new system, this behavior, if I understand correctly, is equivalent to"shared".The default, non-shared, would be objects that belong, permanently, to exactlyone thread - the one that created them, to the extent that accessing them from another thread would constitute a compiler failure.What I am looking for, then, is to somehow temporarily, or permanently, changethe thread that a specific instance belongs to, transfer ownership to another thread, so to speak, in an atomic manner - so that at no time more than one thread possesses ownership of the object - thus gaining, basically, the guaranteed thread-safety of a non-shared object with the convenience of a shared object. We've discussed creating per-thread GCs in Tango to eliminate the problem of "stop the world" collections. Transferral of ownership is complicated with such a model, however, if the object being transferred represents a resource. Everything else you can just .dup (ie. perform a deep copy), but obviously not singletons. I'd be inclined to say that this is a limitation you'll just have to deal with when designing your program. Make one thread the "owner" of the object and have other threads interact with it basically via messaging. This idea of per-thread GCs dovetails perfectly with 'shared' as well, since there's no way in D 1.0 to flag the creation of static data. In D 2.0 however, it sounds like all such data either must be labeled 'shared' or can be made thread-local as well. Totally awesome. Of course, that still means that memory backing shared data will leak in the absence of a GC, so either this would have to be stated and the user would have to deal with it, or there would still need to be a global "stop the world" GC specifically for the shared data. In the latter case, I'd probably default the GC to disabled so the user would either collect manually or enable it if he doesn't care about an occasional "stop the world" collection. Sean
Aug 01 2008
Sean Kelly wrote:== Quote from downs (default_357-line yahoo.de)'s articleSome good points. One thing that will likely happen with shared GC is that there will be relativity a very small amount of shared memory needed. Therefore GC collection on the shared memory might be fast enough for many people. If there's a lot of memory being shared its a sign that something might be wrong. That's because a huge amount of shared memory means that the benefit of multi-threading will seriously be diminished. Also maybe "shared" could eventually use a different kinda GC which is more optimal for shared memory. If there was a way to say which threads had read/write (or both) access to different shared memories then not all threads would need to be stopped. -JoelWalter Bright wrote:synchronization blocks are used to prevent interference.downs wrote:Okay. In the current system, every object "belongs" to every thread equally -I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.In the new system, this behavior, if I understand correctly, is equivalent to"shared".The default, non-shared, would be objects that belong, permanently, to exactlyone thread - the one that created them, to the extent that accessing them from another thread would constitute a compiler failure.What I am looking for, then, is to somehow temporarily, or permanently, changethe thread that a specific instance belongs to, transfer ownership to another thread, so to speak, in an atomic manner - so that at no time more than one thread possesses ownership of the object - thus gaining, basically, the guaranteed thread-safety of a non-shared object with the convenience of a shared object. We've discussed creating per-thread GCs in Tango to eliminate the problem of "stop the world" collections. Transferral of ownership is complicated with such a model, however, if the object being transferred represents a resource. Everything else you can just .dup (ie. perform a deep copy), but obviously not singletons. I'd be inclined to say that this is a limitation you'll just have to deal with when designing your program. Make one thread the "owner" of the object and have other threads interact with it basically via messaging. This idea of per-thread GCs dovetails perfectly with 'shared' as well, since there's no way in D 1.0 to flag the creation of static data. In D 2.0 however, it sounds like all such data either must be labeled 'shared' or can be made thread-local as well. Totally awesome. Of course, that still means that memory backing shared data will leak in the absence of a GC, so either this would have to be stated and the user would have to deal with it, or there would still need to be a global "stop the world" GC specifically for the shared data. In the latter case, I'd probably default the GC to disabled so the user would either collect manually or enable it if he doesn't care about an occasional "stop the world" collection. Sean
Aug 02 2008
Sean Kelly wrote:== Quote from downs (default_357-line yahoo.de)'s articleWould this be an end to 'static' variables?Walter Bright wrote:synchronization blocks are used to prevent interference.downs wrote:Okay. In the current system, every object "belongs" to every thread equally -I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.In the new system, this behavior, if I understand correctly, is equivalent to"shared".The default, non-shared, would be objects that belong, permanently, to exactlyone thread - the one that created them, to the extent that accessing them from another thread would constitute a compiler failure.What I am looking for, then, is to somehow temporarily, or permanently, changethe thread that a specific instance belongs to, transfer ownership to another thread, so to speak, in an atomic manner - so that at no time more than one thread possesses ownership of the object - thus gaining, basically, the guaranteed thread-safety of a non-shared object with the convenience of a shared object. We've discussed creating per-thread GCs in Tango to eliminate the problem of "stop the world" collections. Transferral of ownership is complicated with such a model, however, if the object being transferred represents a resource. Everything else you can just .dup (ie. perform a deep copy), but obviously not singletons. I'd be inclined to say that this is a limitation you'll just have to deal with when designing your program. Make one thread the "owner" of the object and have other threads interact with it basically via messaging. This idea of per-thread GCs dovetails perfectly with 'shared' as well, since there's no way in D 1.0 to flag the creation of static data. In D 2.0 however, it sounds like all such data either must be labeled 'shared' or can be made thread-local as well.
Aug 14 2008
Don wrote:Sean Kelly wrote:I think that's the only feasible option for D1, which is why I'm hesitant to pursue per-thread GCs. It's a restriction that would have no language support but rather rely on convention to prevent crashes. For D2 I think it may be possible to rely on the transitivity of 'shared' and to use this type qualifier to allocate from a central "stop the world" GC. The tricky thing here is that local data would have to be copied if it were to be referenced only from the shared area, similar to an .idup I suppose. Sean== Quote from downs (default_357-line yahoo.de)'s articleWould this be an end to 'static' variables?Walter Bright wrote:synchronization blocks are used to prevent interference.downs wrote:Okay. In the current system, every object "belongs" to every thread equally -I am looking for a safe way to transfer ownership of a single object between threads. Like, for instance, a "unique Object foo" would behave like a shared Object, but the compiler would treat it like a nonshared object for purposes of optimization, and all accesses from the outside would be implicitly synchronized. This could be used for objects that really are only supposed to exist once, but still used in a multithreaded way. Hope that clears things up.Sorry, I still have no idea what you're asking for.In the new system, this behavior, if I understand correctly, is equivalent to"shared".The default, non-shared, would be objects that belong, permanently, to exactlyone thread - the one that created them, to the extent that accessing them from another thread would constitute a compiler failure.What I am looking for, then, is to somehow temporarily, or permanently, changethe thread that a specific instance belongs to, transfer ownership to another thread, so to speak, in an atomic manner - so that at no time more than one thread possesses ownership of the object - thus gaining, basically, the guaranteed thread-safety of a non-shared object with the convenience of a shared object. We've discussed creating per-thread GCs in Tango to eliminate the problem of "stop the world" collections. Transferral of ownership is complicated with such a model, however, if the object being transferred represents a resource. Everything else you can just .dup (ie. perform a deep copy), but obviously not singletons. I'd be inclined to say that this is a limitation you'll just have to deal with when designing your program. Make one thread the "owner" of the object and have other threads interact with it basically via messaging. This idea of per-thread GCs dovetails perfectly with 'shared' as well, since there's no way in D 1.0 to flag the creation of static data. In D 2.0 however, it sounds like all such data either must be labeled 'shared' or can be made thread-local as well.
Aug 14 2008
Walter Bright wrote:downs wrote:Perhaps this has already been discussed, but there seems another upcoming arms race between probably - NVIDIA/CUDA, currently available 200+ cores available at $500 - Intel multicore, probably available in 12+ months competing in - scientific number-crunching - life video encoding (hot topic) I think it would be a BIG marketing effect for D, if it could support the NVIDIA/CUDA system. Probably it would even get payed by NVIDIA. HelmutWalter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.
Jul 31 2008
On Thu, 31 Jul 2008 19:15:03 +0400, Helmut Leitner <leitner wikiservice.at> wrote:Walter Bright wrote:Other system to take into an account is Playstation 3. It has 7 cores, it runs Linux (YellowDog/Ubuntu/Gentoo...), it is cheap, it is available to everyone. The PS3's hardware has also been used to build supercomputers for high-performance computing. IIRC, it used to have the best cost/GFLOPS ratio some time ago. PS3 uses a GCC compiler which is freely available (I love GPL for that reason) so a GDC is a matter of time (and some effort). BTW, gdc is already ported to Playstation Portable. As a result, we could use a PS3 as a basis for an upcoming cuncurrent programming support in D. I just don't see any other *real* possibilities to get 4 or more cores for a low price.downs wrote:Perhaps this has already been discussed, but there seems another upcoming arms race between probably - NVIDIA/CUDA, currently available 200+ cores available at $500 - Intel multicore, probably available in 12+ months competing in - scientific number-crunching - life video encoding (hot topic) I think it would be a BIG marketing effect for D, if it could support the NVIDIA/CUDA system. Probably it would even get payed by NVIDIA. HelmutWalter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.
Jul 31 2008
Koroskin Denis wrote:As a result, we could use a PS3 as a basis for an upcoming cuncurrent programming support in D. I just don't see any other *real* possibilities to get 4 or more cores for a low price.All NVIDIA graphics boards from 8400 up are usable via the CUDA interface. The newest GT200 chip that is build into the GTX-280 boards (GTX-260 has a just a lower core count) contains 240 cores. There is a number-crunching-only version of these graphics boards, called TESLA. The hi-end-boards promise to reach 1 TFLOP (single precision) and about 0.1 TFLOP (double precision). This is existing technology that is in the market.
Jul 31 2008
Helmut Leitner:This is existing technology that is in the market.And it's working fast as hell already, I have tried CUDA some on my GPU :-) There's an impressive demo named Particles: http://www.youtube.com/watch?v=U5eJ8RdR68I http://www.youtube.com/watch?v=RqduA7myZok It works like this on a card that costs about 70-80 euro, and it's amazing. Bye, bearophile
Jul 31 2008
Helmut Leitner wrote:Walter Bright wrote:This is a library realm topic, given the ability to mixin optimal code per the BLADE-esque technique.downs wrote:Perhaps this has already been discussed, but there seems another upcoming arms race between probably - NVIDIA/CUDA, currently available 200+ cores available at $500 - Intel multicore, probably available in 12+ months competing in - scientific number-crunching - life video encoding (hot topic) I think it would be a BIG marketing effect for D, if it could support the NVIDIA/CUDA system. Probably it would even get payed by NVIDIA. HelmutWalter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.
Jul 31 2008
Kyle Furlong wrote:Helmut Leitner wrote:I spoke too soon, this would require asm support for those processors.Walter Bright wrote:This is a library realm topic, given the ability to mixin optimal code per the BLADE-esque technique.downs wrote:Perhaps this has already been discussed, but there seems another upcoming arms race between probably - NVIDIA/CUDA, currently available 200+ cores available at $500 - Intel multicore, probably available in 12+ months competing in - scientific number-crunching - life video encoding (hot topic) I think it would be a BIG marketing effect for D, if it could support the NVIDIA/CUDA system. Probably it would even get payed by NVIDIA. HelmutWalter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics. I suggested to Andrei and Bartosz just the other day that I don't expect the value in this model will be readily apparent. I'm pretty sure it won't be, as the issues are hard to understand. But the issues being hard to understand is exactly why this model is needed. There are surely several articles, papers, and tutorials in this :-)Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.
Jul 31 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articledowns wrote:In my opinion, the easiest way to describe the hardware side of things is simply to say that the CPU does the exact same thing as the optimizer in the compiler, only it does this dynamically as the code is executing. The rest just involves ideas for how to constrain CPU and compiler optimizations so the app behaves as expected when concurrency is involved. In your defense, "volatile" is a perfectly suitable minimum for D, so you did get the gist of the issue, even at the outset. The catch is that, while "volatile" controls the compiler, you still need to control the CPU, so inline ASM is required as well. Fortunately, D has that :-) So please give yourself a bit more credit here. D1 works perfectly well for concurrent programming. It just support this is a sufficiently non-obvious way that only people who understand the issues involved are likely to realize it. But as most of this stuff should really be in a library anyway, I don't see a problem with things as they are. Finding a way for the average user to do safe concurrent programming is an entirely different issue in my opinion, and has only really been "solved," in my opinion, in the functional programming realm. And that's by eliminating data sharing--the bane of imperative languages everywhere.Walter Bright wrote:A couple years ago, I was in a room with 30 of the top C++ programmers in the country. The topic was a 2 day conference on how to support multithreading in C++. It soon became clear that only two people in the room understood the issues (and I wasn't one of them). I think I understand the issues now, but it has taken a long time and repeatedly reading the papers about it. It is not simple, and it's about as intuitive as quantum mechanics.Steven Schveighoffer wrote:He's probably right.I would hazard to guess that adopting this would cause a larger rift than const.I disagree. D is a systems language first and foremost. Much of the rest can be done in library code. That isn't to say that I wouldn't like improved multiprogramming support in the language for the things that are awkward to do in library code (a thread-local storage class, for example), but trying to prevent the user from shooting himself in the foot is unnecessary. Particularly if doing so incurs a runtime cost that is not avoidable.I meant that programmers will no longer find the language acceptable if it doesn't offer better support.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Since when is it the language's job to tell us what's acceptable and what's not?There was some talk in the C++0x memory model discussion that Intel was actually planning on providing equivalent or stronger guarantees for future processors rather than weaker ones. I'll admit to having been very surprised at the time, but apparently they feel that they can do so and still provide the performance people expect. I guess the resounding failure of the Itanic forced them to rethink what was required for a successful new processor design. If I remember correctly, it was Paul McKenney that brought this up if you feel like searching the archives. SeanD is not only meant to be more than an x86 only language, the x86 family steadily moves towards the relaxed sequential consistency model. The threading model supported by Java and the upcoming C++0x release are both based on the relaxed model, that is clearly where the industry expects things to go, and I see no reason to believe otherwise.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.The double checked locking "bug" is only a bug on certain architectures, none of which D is supported on.
Jul 31 2008
Sean Kelly wrote:In my opinion, the easiest way to describe the hardware side of things is simply to say that the CPU does the exact same thing as the optimizer in the compiler, only it does this dynamically as the code is executing. The rest just involves ideas for how to constrain CPU and compiler optimizations so the app behaves as expected when concurrency is involved. In your defense, "volatile" is a perfectly suitable minimum for D, so you did get the gist of the issue, even at the outset. The catch is that, while "volatile" controls the compiler, you still need to control the CPU, so inline ASM is required as well. Fortunately, D has that :-) So please give yourself a bit more credit here. D1 works perfectly well for concurrent programming. It just support this is a sufficiently non-obvious way that only people who understand the issues involved are likely to realize it. But as most of this stuff should really be in a library anyway, I don't see a problem with things as they are.Java has synchronization and volatile, and it isn't good enough.Finding a way for the average user to do safe concurrent programming is an entirely different issue in my opinion, and has only really been "solved," in my opinion, in the functional programming realm. And that's by eliminating data sharing--the bane of imperative languages everywhere.D will eliminate implicit data sharing. To share data, you'll have to mark it as shared, and with the marking will come extra help in fences and synchronization. I've looked at the two classic multithreaded problems - double checked locking, and sequential consistency between threads. This model prevents both of them from happening.I disagree. D is a systems language first and foremost. Much of the rest can be done in library code. That isn't to say that I wouldn't like improved multiprogramming support in the language for the things that are awkward to do in library code (a thread-local storage class, for example), but trying to prevent the user from shooting himself in the foot is unnecessary. Particularly if doing so incurs a runtime cost that is not avoidable.It is avoidable if you're willing to insert a cast. Putting in the cast says "I know how to handle the wild west, let me do it." The cast has zero runtime cost.There was some talk in the C++0x memory model discussion that Intel was actually planning on providing equivalent or stronger guarantees for future processors rather than weaker ones. I'll admit to having been very surprised at the time, but apparently they feel that they can do so and still provide the performance people expect. I guess the resounding failure of the Itanic forced them to rethink what was required for a successful new processor design. If I remember correctly, it was Paul McKenney that brought this up if you feel like searching the archives.Intel may be reacting to the disastrous problems conventional languages have with this. If it is solved (and I think we have a credible solution), Intel may change their direction.
Jul 31 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleSean Kelly wrote:But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)In my opinion, the easiest way to describe the hardware side of things is simply to say that the CPU does the exact same thing as the optimizer in the compiler, only it does this dynamically as the code is executing. The rest just involves ideas for how to constrain CPU and compiler optimizations so the app behaves as expected when concurrency is involved. In your defense, "volatile" is a perfectly suitable minimum for D, so you did get the gist of the issue, even at the outset. The catch is that, while "volatile" controls the compiler, you still need to control the CPU, so inline ASM is required as well. Fortunately, D has that :-) So please give yourself a bit more credit here. D1 works perfectly well for concurrent programming. It just support this is a sufficiently non-obvious way that only people who understand the issues involved are likely to realize it. But as most of this stuff should really be in a library anyway, I don't see a problem with things as they are.Java has synchronization and volatile, and it isn't good enough.So "shared" will tell the compiler to automatically fence, etc? Will any actual enforcement be done? And if so, will this be at compile time, run time, or both?Finding a way for the average user to do safe concurrent programming is an entirely different issue in my opinion, and has only really been "solved," in my opinion, in the functional programming realm. And that's by eliminating data sharing--the bane of imperative languages everywhere.D will eliminate implicit data sharing. To share data, you'll have to mark it as shared, and with the marking will come extra help in fences and synchronization. I've looked at the two classic multithreaded problems - double checked locking, and sequential consistency between threads. This model prevents both of them from happening.I think that cast is already used far too much as a standard programming mechanism in D 2.0. And I'll admit that I don't entirely understand why you don't like const_cast but assertUnique or whatever does exactly that behind the scenes. Should we consider cast to be an evil red flag-throwing feature or not?I disagree. D is a systems language first and foremost. Much of the rest can be done in library code. That isn't to say that I wouldn't like improved multiprogramming support in the language for the things that are awkward to do in library code (a thread-local storage class, for example), but trying to prevent the user from shooting himself in the foot is unnecessary. Particularly if doing so incurs a runtime cost that is not avoidable.It is avoidable if you're willing to insert a cast. Putting in the cast says "I know how to handle the wild west, let me do it." The cast has zero runtime cost.That's certainly possible. But I do think it would require the solution to be pervasive rather than just in D if Intel were to pay attention. That said, I'd most prefer release consistency for a hardware memory model (somewhat like the Itanium) combined with hardware transactional memory. I'm actually a bit disappointed that the Itanium wasn't successful. The basic design was solid. SeanThere was some talk in the C++0x memory model discussion that Intel was actually planning on providing equivalent or stronger guarantees for future processors rather than weaker ones. I'll admit to having been very surprised at the time, but apparently they feel that they can do so and still provide the performance people expect. I guess the resounding failure of the Itanic forced them to rethink what was required for a successful new processor design. If I remember correctly, it was Paul McKenney that brought this up if you feel like searching the archives.Intel may be reacting to the disastrous problems conventional languages have with this. If it is solved (and I think we have a credible solution), Intel may change their direction.
Jul 31 2008
Sean Kelly Wrote:That's certainly possible. But I do think it would require the solution to be pervasive rather than just in D if Intel were to pay attention. That said, I'd most prefer release consistency for a hardware memory model (somewhat like the Itanium) combined with hardware transactional memory. I'm actually a bit disappointed that the Itanium wasn't successful. The basic design was solid.haven't read bartosz' stuff yet, so no comment on that. but with all due respect. about itanium's design. what a piece of rotten shit that is. they use predicated execution like it's jesus on tv. of course that didn't catch up. itanium was a stillborn from day 1.
Jul 31 2008
Sean Kelly wrote:From talking to people who do large scale multithreaded Java programs, it is not fine. The problem is that there is no way to look at a non-trivial piece of code that you didn't write, and determine if it has dependencies on sequential consistency or not. I'm not arguing that a thread expert cannot make a thread correct program in Java and C++. They can. The problem is the inability to verify such correctness, no help is available from the language, and the dearth of such experts.Java has synchronization and volatile, and it isn't good enough.But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)So "shared" will tell the compiler to automatically fence, etc?Yes.Will any actual enforcement be done? And if so, will this be at compile time, run time, or both?Compile time - it's part of the static type checking system.Cast is the red flag raising feature. The thing about it is that when you review code, the cast is where you look for bugs. With Java and C++, you have *no clue* where to look for bugs. It reduces the problem domain from the entire program to a (hopefully) manageable small subset.It is avoidable if you're willing to insert a cast. Putting in the cast says "I know how to handle the wild west, let me do it." The cast has zero runtime cost.I think that cast is already used far too much as a standard programming mechanism in D 2.0. And I'll admit that I don't entirely understand why you don't like const_cast but assertUnique or whatever does exactly that behind the scenes. Should we consider cast to be an evil red flag-throwing feature or not?
Jul 31 2008
Walter Bright Wrote:Sean Kelly wrote:yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.From talking to people who do large scale multithreaded Java programs, it is not fine. The problem is that there is no way to look at a non-trivial piece of code that you didn't write, and determine if it has dependencies on sequential consistency or not. I'm not arguing that a thread expert cannot make a thread correct program in Java and C++. They can. The problem is the inability to verify such correctness, no help is available from the language, and the dearth of such experts.Java has synchronization and volatile, and it isn't good enough.But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)So "shared" will tell the compiler to automatically fence, etc?Yes.
Jul 31 2008
superdan wrote:Walter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Jul 31 2008
Walter Bright Wrote:superdan wrote:i grok that. my problem is that your shared doesn't help me with writing good code in that case. ++x is just wrong for shared x. i'd rather have it disabled or somethin'.Walter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Jul 31 2008
superdan wrote:i grok that. my problem is that your shared doesn't help me with writing good code in that case. ++x is just wrong for shared x. i'd rather have it disabled or somethin'.Actually, the current plan is that ++ would be disabled for shared lvalues. Reads and writes to them would be done through intrinsic functions, which would make clear the order in which reads and writes are done. Sure, it won't be pretty, but there won't be any ambiguity of the order in which things happen.
Aug 01 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articlesuperdan wrote:A totally worthwhile tradeoff IMO. The alternative would be to have ++ call INC if supported or a CAS loop if not, and that's a hidden cost that may surprise users. It could always be enabled later if needed anyway. Oh, and darn you for getting me moderately enthusiastic for D 2.0 :-) Seani grok that. my problem is that your shared doesn't help me with writing good code in that case. ++x is just wrong for shared x. i'd rather have it disabled or somethin'.Actually, the current plan is that ++ would be disabled for shared lvalues. Reads and writes to them would be done through intrinsic functions, which would make clear the order in which reads and writes are done. Sure, it won't be pretty, but there won't be any ambiguity of the order in which things happen.
Aug 01 2008
Sean Kelly wrote:I'm surprised, we expected much more flak about that <g>. The idea is to screw everything down tight like this, see how it goes, and then experience will tell us where we need to loosen things up.Sure, it won't be pretty, but there won't be any ambiguity of the order in which things happen.A totally worthwhile tradeoff IMO. The alternative would be to have ++ call INC if supported or a CAS loop if not, and that's a hidden cost that may surprise users. It could always be enabled later if needed anyway.Oh, and darn you for getting me moderately enthusiastic for D 2.0 :-)I for one am very enthusiastic about the new threading model. The real validation would be when other languages start copying it!
Aug 01 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articlesuperdan wrote:Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe. SeanWalter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Aug 01 2008
Sean Kelly Wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s articlei don't think so. reading must be still fenced if at least one thread writes to it. walt is correct.superdan wrote:Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe. SeanWalter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Aug 01 2008
== Quote from superdan (super dan.org)'s articleSean Kelly Wrote:it. walt is correct. Yeah, but the "i++" is safe, which is all I was implying. Technically the read doesn't even need to be fenced so long as the reader doesn't care if they then operate on a stale value, but it's rare for that to be the case. However, I think I do use this approach in core.Thread in Tango for a flag somewhere. Kinda risky, but I don't want to pay for the ~70 cycles a lock would require and I really don't care if the value is a bit stale. But in these instances, I think it's totally okay to require the user to take extra steps to indicate that this is his intention. core.Atomic, for example, has msync.raw to indicate that no synchronization should occur, but a bidirectional fence is the default if no sync flag is passed. Sean== Quote from Walter Bright (newshound1 digitalmars.com)'s articlei don't think so. reading must be still fenced if at least one thread writes tosuperdan wrote:Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.Walter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Aug 01 2008
Sean Kelly Wrote:== Quote from superdan (super dan.org)'s articlemakes sense. but i guess we agree that that is the rare case in which you're ok with a race. the usual case is you don't want a race. so i think it's fair that the rare case requires a cast. walt seems to have gotten the default right as far as i can tell.Sean Kelly Wrote:it. walt is correct. Yeah, but the "i++" is safe, which is all I was implying. Technically the read doesn't even need to be fenced so long as the reader doesn't care if they then operate on a stale value, but it's rare for that to be the case. However, I think I do use this approach in core.Thread in Tango for a flag somewhere. Kinda risky, but I don't want to pay for the ~70 cycles a lock would require and I really don't care if the value is a bit stale. But in these instances, I think it's totally okay to require the user to take extra steps to indicate that this is his intention. core.Atomic, for example, has msync.raw to indicate that no synchronization should occur, but a bidirectional fence is the default if no sync flag is passed.== Quote from Walter Bright (newshound1 digitalmars.com)'s articlei don't think so. reading must be still fenced if at least one thread writes tosuperdan wrote:Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.Walter Bright Wrote:If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.yech. so i write this: ++a; ++b; ++c; and very different code comes down the pike depending on a or b or c being shared. not easy to clarify the code is correct. this ain't cool.So "shared" will tell the compiler to automatically fence, etc?Yes.
Aug 01 2008
superdan wrote:makes sense. but i guess we agree that that is the rare case in which you're ok with a race. the usual case is you don't want a race. so i think it's fair that the rare case requires a cast. walt seems to have gotten the default right as far as i can tell.It's not just me. There are several people who've been hammering away at how this needs to work, including Andrei, Bartosz, David Held, Brad Roberts, and Eric Niebler.
Aug 01 2008
Sean Kelly wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s articleIf you've got only one thread, why is it shared ? If it is shared, there's the possibility of multiple threads, and so the code is wrong wrong wrong.If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.
Aug 01 2008
Walter Bright Wrote:Sean Kelly wrote:i think he means a different case. you have many threads alright. but only one is incrementin'. others are just readin'.== Quote from Walter Bright (newshound1 digitalmars.com)'s articleIf you've got only one thread, why is it shared ? If it is shared, there's the possibility of multiple threads, and so the code is wrong wrong wrong.If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.
Aug 01 2008
superdan wrote:Walter Bright Wrote:If Sean means that the code is synchronized so only one thread has access, he is correct. In the proposed threading model, within a synchronized function, the shared object data can be accessed without fences and the ++ will work. Essentially, within a synchronized function, the 'this' object becomes tail-shared. I know, AAAIIIEEEEE!Sean Kelly wrote:i think he means a different case. you have many threads alright. but only one is incrementin'. others are just readin'.== Quote from Walter Bright (newshound1 digitalmars.com)'s articleIf you've got only one thread, why is it shared ? If it is shared, there's the possibility of multiple threads, and so the code is wrong wrong wrong.If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.
Aug 01 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleSean Kelly wrote:Only one writer, multiple readers. But this is assuming the INC is issued to the CPU rather than the compiler deciding to just hold onto the value in a register or something. ie. I think "shared" implies more than fences, yes? It's also an indication to the compiler than certain optimizations may not be performed, roughly similar to 'volatile' in D 1.0. Sean== Quote from Walter Bright (newshound1 digitalmars.com)'s articleIf you've got only one thread, why is it shared ? If it is shared, there's the possibility of multiple threads, and so the code is wrong wrong wrong.If conventional code were generated for i++, and i was accessed from multiple threads, the code is *broken*.Not necessarily. If i is a 32-bit number and only one thread is doing the writing then the code could be perfectly safe.
Aug 01 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleSean Kelly wrote:That's the problem with providing such fundamental support for lock-free programming: people will try it, and they'll invariably get it wrong. This is actually the reason why I like the minimalist approach of D 1.0 with 'volatile'. Support for lock-free is sufficiently subtle that it's unlikely to be used outside of library code.From talking to people who do large scale multithreaded Java programs, it is not fine. The problem is that there is no way to look at a non-trivial piece of code that you didn't write, and determine if it has dependencies on sequential consistency or not. I'm not arguing that a thread expert cannot make a thread correct program in Java and C++. They can. The problem is the inability to verify such correctness, no help is available from the language, and the dearth of such experts.Java has synchronization and volatile, and it isn't good enough.But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)I've got to admit that I actually like this idea. It's a breaking change that will trigger run-time failures in code when the feature is deployed, but in the kind of multithreaded apps I write I'd be labeling perhaps two variable declarations in the entire app. Would it be possible to do something like this and have the compiler realize it's safe: class SharedObj { void go() {} } shared Mutex m; shared SharedObj o; static this() { m = new Mutex; o = new SharedObj; } void someFunc() { synchronized( m ) { o.go(); } }So "shared" will tell the compiler to automatically fence, etc?Yes.Will any actual enforcement be done? And if so, will this be at compile time, run time, or both?Compile time - it's part of the static type checking system.Java and C++ have cast too, though. Unfortunately, it's not easy to grep for 'cast' in Java because of the syntax, but I use the C++ style casts religiously there and I like that they "jump out" at me when reading the code. From a quick scan of an old project of mine, outside systems code where casting is often necessary as a matter of course, the precious few casts in the app are mostly for warning-free comparisons of signed and unsigned integers in situations I know the values will be in bounds. Which reminds me... weren't we going to get tighter conversion rules for concrete types? I'd love to have the D compiler yell at me for these things like my C++ compiler does. Back on track... I suppose I'm just worried that my apps will end up with casts all over the place simply to allow me to operate normally, thus diluting the usefulness of this red flag. But that's idle speculation so perhaps my concern is unfounded.Cast is the red flag raising feature. The thing about it is that when you review code, the cast is where you look for bugs. With Java and C++, you have *no clue* where to look for bugs. It reduces the problem domain from the entire program to a (hopefully) manageable small subset.It is avoidable if you're willing to insert a cast. Putting in the cast says "I know how to handle the wild west, let me do it." The cast has zero runtime cost.I think that cast is already used far too much as a standard programming mechanism in D 2.0. And I'll admit that I don't entirely understand why you don't like const_cast but assertUnique or whatever does exactly that behind the scenes. Should we consider cast to be an evil red flag-throwing feature or not?
Jul 31 2008
Sean Kelly Wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s articlefraid you might have a slightly specialized definition of what lock-free code is. i think you say that cas-based shit is lock free. but here, this is lock free: data = 5.4; dataThere = true; people use lock-free *everywhere*. just they don't call it that way. they just synchronize through atomic assignments. i'm not sure at this point how d's shared will improve the above. if i understand that shit correctly you define data and dataThere as shared. then you know assignments occur in the proper sequence (because of the inserted fences and shit). if they weren't shared they could be assigned in the wrong order but nobody could tell. it's like the shit in the forest that don't stink because nobody's smellin'. and if they weren't shared they wouldn't be shareable to start with. so the whole shit works. is that true walt?Sean Kelly wrote:That's the problem with providing such fundamental support for lock-free programming: people will try it, and they'll invariably get it wrong. This is actually the reason why I like the minimalist approach of D 1.0 with 'volatile'. Support for lock-free is sufficiently subtle that it's unlikely to be used outside of library code.From talking to people who do large scale multithreaded Java programs, it is not fine. The problem is that there is no way to look at a non-trivial piece of code that you didn't write, and determine if it has dependencies on sequential consistency or not. I'm not arguing that a thread expert cannot make a thread correct program in Java and C++. They can. The problem is the inability to verify such correctness, no help is available from the language, and the dearth of such experts.Java has synchronization and volatile, and it isn't good enough.But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)yeh same here. good mt apps share little and with care.I've got to admit that I actually like this idea. It's a breaking change that will trigger run-time failures in code when the feature is deployed, but in the kind of multithreaded apps I write I'd be labeling perhaps two variable declarations in the entire app.So "shared" will tell the compiler to automatically fence, etc?Yes.Will any actual enforcement be done? And if so, will this be at compile time, run time, or both?Compile time - it's part of the static type checking system.Would it be possible to do something like this and have the compiler realize it's safe: class SharedObj { void go() {} } shared Mutex m; shared SharedObj o; static this() { m = new Mutex; o = new SharedObj; } void someFunc() { synchronized( m ) { o.go(); } }fuck yeah walt. put me down for that one too.Java and C++ have cast too, though. Unfortunately, it's not easy to grep for 'cast' in Java because of the syntax, but I use the C++ style casts religiously there and I like that they "jump out" at me when reading the code. From a quick scan of an old project of mine, outside systems code where casting is often necessary as a matter of course, the precious few casts in the app are mostly for warning-free comparisons of signed and unsigned integers in situations I know the values will be in bounds. Which reminds me... weren't we going to get tighter conversion rules for concrete types? I'd love to have the D compiler yell at me for these things like my C++ compiler does.Cast is the red flag raising feature. The thing about it is that when you review code, the cast is where you look for bugs. With Java and C++, you have *no clue* where to look for bugs. It reduces the problem domain from the entire program to a (hopefully) manageable small subset.It is avoidable if you're willing to insert a cast. Putting in the cast says "I know how to handle the wild west, let me do it." The cast has zero runtime cost.I think that cast is already used far too much as a standard programming mechanism in D 2.0. And I'll admit that I don't entirely understand why you don't like const_cast but assertUnique or whatever does exactly that behind the scenes. Should we consider cast to be an evil red flag-throwing feature or not?
Jul 31 2008
superdan wrote:fraid you might have a slightly specialized definition of what lock-free code is. i think you say that cas-based shit is lock free. but here, this is lock free: data = 5.4; dataThere = true; people use lock-free *everywhere*. just they don't call it that way. they just synchronize through atomic assignments. i'm not sure at this point how d's shared will improve the above. if i understand that shit correctly you define data and dataThere as shared. then you know assignments occur in the proper sequence (because of the inserted fences and shit). if they weren't shared they could be assigned in the wrong order but nobody could tell. it's like the shit in the forest that don't stink because nobody's smellin'. and if they weren't shared they wouldn't be shareable to start with. so the whole shit works. is that true walt?Yes.
Aug 01 2008
== Quote from superdan (super dan.org)'s articleSean Kelly Wrote:is. i think you say that cas-based shit is lock free. but here, this is lock free:== Quote from Walter Bright (newshound1 digitalmars.com)'s articlefraid you might have a slightly specialized definition of what lock-free codeSean Kelly wrote:That's the problem with providing such fundamental support for lock-free programming: people will try it, and they'll invariably get it wrong. This is actually the reason why I like the minimalist approach of D 1.0 with 'volatile'. Support for lock-free is sufficiently subtle that it's unlikely to be used outside of library code.From talking to people who do large scale multithreaded Java programs, it is not fine. The problem is that there is no way to look at a non-trivial piece of code that you didn't write, and determine if it has dependencies on sequential consistency or not. I'm not arguing that a thread expert cannot make a thread correct program in Java and C++. They can. The problem is the inability to verify such correctness, no help is available from the language, and the dearth of such experts.Java has synchronization and volatile, and it isn't good enough.But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)data = 5.4; dataThere = true; people use lock-free *everywhere*. just they don't call it that way. they justsynchronize through atomic assignments. Yeah that's true. What drives me crazy about this is that there's no way to tell from inspection whether the programmer knew what they were doing. You end up having to check all the uses of 'data' to find out. I guess this is Walter's point about static checking. If 'data' were shared then I could trust that it would "just work." In Tango, you'd do: atomicStore( data, 5.4 ); And that would label the assignment as "safe" to a reader, but other uses of 'data' could still be broken.i'm not sure at this point how d's shared will improve the above. if iunderstand that shit correctly you define data and dataThere as shared. then you know assignments occur in the proper sequence (because of the inserted fences and shit). if they weren't shared they could be assigned in the wrong order but nobody could tell. it's like the shit in the forest that don't stink because nobody's smellin'. and if they weren't shared they wouldn't be shareable to start with. so the whole shit works. is that true walt? This sounds right. My only concern for the injected fences is that it won't always result in optimal code for what the user is doing. But it will be safe, which I guess is pretty important (by "optimal" I mean that you don't always need fences for an operation depending on the hardware and on whether you care about code movement across the operation). Sean
Aug 01 2008
Sean Kelly wrote:This sounds right. My only concern for the injected fences is that it won't always result in optimal code for what the user is doing. But it will be safe, which I guess is pretty important (by "optimal" I mean that you don't always need fences for an operation depending on the hardware and on whether you care about code movement across the operation).You're right, it won't always be optimal. The idea is to get it right and then just optimize the bottlenecks.
Aug 02 2008
Sean Kelly wrote:Would it be possible to do something like this and have the compiler realize it's safe: class SharedObj { void go() {} } shared Mutex m; shared SharedObj o; static this() { m = new Mutex; o = new SharedObj; } void someFunc() { synchronized( m ) { o.go(); } }I don't know, but I doubt it.But that is useless for multithreading, because Java and C++ types have no notion of sharing.Cast is the red flag raising feature. The thing about it is that when you review code, the cast is where you look for bugs. With Java and C++, you have *no clue* where to look for bugs. It reduces the problem domain from the entire program to a (hopefully) manageable small subset.Java and C++ have cast too, though.Which reminds me... weren't we going to get tighter conversion rules for concrete types? I'd love to have the D compiler yell at me for these things like my C++ compiler does.All in goood time, my pretty <rubs hands>Back on track... I suppose I'm just worried that my apps will end up with casts all over the place simply to allow me to operate normally, thus diluting the usefulness of this red flag. But that's idle speculation so perhaps my concern is unfounded.I don't know how it will work out yet in practice, either. But I suspect if casts wind up all over the place, that may be a sign that there are too many connection points between the shared and unshared worlds, and perhaps a code refactoring is in order.
Jul 31 2008
Sean Kelly Wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s articlei'm afraid c++ and c++0x and java are "actually fine" to write multiprocessing code if the coder is fucking superman on steroids after an overdose of ritalin. as far as threads are concerned these are as good as brainfuck to code in. you also say d1 is perfectly fine to do multiprocessing in. i think that's at best naive. sorry sean.Sean Kelly wrote:But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)In my opinion, the easiest way to describe the hardware side of things is simply to say that the CPU does the exact same thing as the optimizer in the compiler, only it does this dynamically as the code is executing. The rest just involves ideas for how to constrain CPU and compiler optimizations so the app behaves as expected when concurrency is involved. In your defense, "volatile" is a perfectly suitable minimum for D, so you did get the gist of the issue, even at the outset. The catch is that, while "volatile" controls the compiler, you still need to control the CPU, so inline ASM is required as well. Fortunately, D has that :-) So please give yourself a bit more credit here. D1 works perfectly well for concurrent programming. It just support this is a sufficiently non-obvious way that only people who understand the issues involved are likely to realize it. But as most of this stuff should really be in a library anyway, I don't see a problem with things as they are.Java has synchronization and volatile, and it isn't good enough.
Jul 31 2008
== Quote from superdan (super dan.org)'s articleSean Kelly Wrote:code if the coder is fucking superman on steroids after an overdose of ritalin. as far as threads are concerned these are as good as brainfuck to code in. you also say d1 is perfectly fine to do multiprocessing in. i think that's at best naive. sorry sean. No problem. Just because I think they're all functional doesn't mean I think they make for easily verifiable or safe code. I'd agree with you that most actual multithreaded code in these languages is garbage. Though most plain old code I've seen is garbage anyway, so I guess it's no surprise that the actually difficult stuff would follow suit. As far as verifiability is concerned though, CSP and the other process algebras are darn nice. Sean== Quote from Walter Bright (newshound1 digitalmars.com)'s articlei'm afraid c++ and c++0x and java are "actually fine" to write multiprocessingSean Kelly wrote:But volatile in Java is completely different. And Java doesn't support inline ASM. That said, Java post JSR-133 (ie. Java today) is actually fine. The C++ 0x people simply didn't copy Java because the Java memory model is too strict to appease the performance-crazed folks in the group :-)In my opinion, the easiest way to describe the hardware side of things is simply to say that the CPU does the exact same thing as the optimizer in the compiler, only it does this dynamically as the code is executing. The rest just involves ideas for how to constrain CPU and compiler optimizations so the app behaves as expected when concurrency is involved. In your defense, "volatile" is a perfectly suitable minimum for D, so you did get the gist of the issue, even at the outset. The catch is that, while "volatile" controls the compiler, you still need to control the CPU, so inline ASM is required as well. Fortunately, D has that :-) So please give yourself a bit more credit here. D1 works perfectly well for concurrent programming. It just support this is a sufficiently non-obvious way that only people who understand the issues involved are likely to realize it. But as most of this stuff should really be in a library anyway, I don't see a problem with things as they are.Java has synchronization and volatile, and it isn't good enough.
Jul 31 2008
superdan wrote:i'm afraid c++ and c++0x and java are "actually fine" to write multiprocessing code if the coder is fucking superman on steroids after an overdose of ritalin.There's also the issue of the person who thinks they know how to write multithreaded code, but don't. Want an example? Just look at some of my older code. This code may "work" well enough that the problems don't appear until years later. Then what? I remember the reaction to Herb Sutter showing some of the things that can go wrong to multithreaded programmers - it was holy ****, I had no idea! Having no compiler help with this is like turning off static type checking. Sure, if you're a good programmer, you don't need static type checking! I believe there is a growing need to be able to statically *prove* things about a program. If that can be done, you don't have to rely on experts being always right. Java, for example, can prove your program is memory safe. Certain classes of bugs cannot happen with Java programs. The more classes of bugs that can be defined out of existence, the easier it will be to verify correctness regardless of the expertise of the programmer.
Jul 31 2008
Walter Bright wrote:Having no compiler help with this is like turning off static type checking. Sure, if you're a good programmer, you don't need static type checking!Lets all just program in Python or one of those other untypesafe languages :) -Joel
Jul 31 2008
JAnderson Wrote:Walter Bright wrote:python is typesafe. just not statically.Having no compiler help with this is like turning off static type checking. Sure, if you're a good programmer, you don't need static type checking!Lets all just program in Python or one of those other untypesafe languages :)
Jul 31 2008
Walter Bright:Java has synchronization and volatile, and it isn't good enough.Java is some years old, while Scala is a new language that runs on the JavaVM that is slowly growing in its usage. In Scala people often use Actor-based concurrency (and someone is starting to use Actors in Java too). Scala contains some 'modern' things, that D may take a look at, instead of using just C/C++/C++0x/Java/Python as reference. Bye, bearophile
Jul 31 2008
Walter Bright, el 30 de julio a las 23:22 me escribiste:Steven Schveighoffer wrote:Tell that to singleton-monkeys =P -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- ¿Qué será lo que hace que una brújula siempre marque el norte? - Ser aguja, nada más, y cumplir su misión. -- Ricardo Vaporeso"Walter Bright" wroteNearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data.
Jul 31 2008
Leandro Lucarella wrote:Tell that to singleton-monkeys =PYeah, and singletons suffer from the double-checked locking bug! Bartosz even found one of those in my code, and I should know better!
Jul 31 2008
"Walter Bright" wroteSteven Schveighoffer wrote:I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'"Walter Bright" wroteNearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data.Yeah, because all us cowboys don't like your kind. Maybe we need to get us a rope and have a lynchin. Seriously, how can you say that the current threadding tools are 'uncontrolled' (i.e. wild west)? I spend lots of time thinking about multithreadded issues, and make sure my software works properly. I think the level of quality for threadding issues depends on the coder, not the tools. In the case of shared/unshared, it's not going to change anything, except now I have to declare things I didn't have to declare before. I.e. having shared/unshared is going to be just as wild as before. I may be wrong, and this shared/unshared thing will be really great for people. But I think it needs a lot of work before it's helpful. In its current incarnation, I'll call it the 'shared wild west' approach :PI would hazard to guess that adopting this would cause a larger rift than const.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Except now instead of the compiler helping you, you have pushed aside that help and said 'I know what I'm doing'. Oops, back to the wild west :)Second, the fact that you can't implicitly cast shared to unshared and vice versa. It's going to make communication between both 'worlds' very error prone, as you will be required to cast for any call from one to the other.I think the reverse is true. Moving data between those worlds is dangerous and needs to be carefully vetted, so requiring an explicit cast will reduce the chance of this happening unintentionally.dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because the compiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread! But the result is, we're back to the same model as before. And now I have to cast everything. Annoying.People will do this just to get their code to work, without thinking about the consequences.True, but having it happen implicitly is even worse, because there's no indication that it is happening.Please let me decide whether I'm far better off. I don't need protection from stuff that doesn't matter. I will still have to lock shared data, and still have to cast to get things to work, so I'm not better off. You can't tell me otherwise, because all this stuff is a figment of your imagination. You have no proof. Until you can show me that I'm better off with an actual example, then I believe we both are equally right :) -SteveEven those that do think about the consequences, can't have the compiler statically check the cast in either direction, so once you cast, you lose all the benefit.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.
Jul 31 2008
Steven Schveighoffer wrote:"Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more. (Programming languages started out with everything being global data, and has moved away from that ever since.)Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'Yeah, because all us cowboys don't like your kind. Maybe we need to get us a rope and have a lynchin. Seriously, how can you say that the current threadding tools are 'uncontrolled' (i.e. wild west)?Because of the common multithreaded bug http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html for one example. There is no threading tool I'm aware of that can prevent or detect such bugs.I spend lots of time thinking about multithreadded issues, and make sure my software works properly. I think the level of quality for threadding issues depends on the coder, not the tools.I believe the tools can make it easier.In the case of shared/unshared, it's not going to change anything, except now I have to declare things I didn't have to declare before. I.e. having shared/unshared is going to be just as wild as before.Why? First of all, unshared data isn't going to have sequential or sync issues, by definition. Already, you've cut the problem domain down by a huge chunk. Next, shared data access will come with fences or sync. That isn't going to guarantee no deadlocks, but it will guarantee sequential consistency, and at the very least will dramatically cut the problem domain down.Except now instead of the compiler helping you, you have pushed aside that help and said 'I know what I'm doing'. Oops, back to the wild west :)If you want the wild west, you have it, if you want compiler help instead, you got it. How is that worse than C++ or Java, where you always have the wild west and no help at all?Non-shared can be implicitly cast to shared, as that is always safe. Just not the other way.True, but having it happen implicitly is even worse, because there's no indication that it is happening.dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because the compiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread! But the result is, we're back to the same model as before. And now I have to cast everything. Annoying.Please let me decide whether I'm far better off.Ok. D offers both - and for the guy maintaining your code, there'll at least be clear indications of where to look for the source of elusive threading bugs. Optlink currently has a threading bug in it. I have no idea where to look for it in the source code.I don't need protection from stuff that doesn't matter. I will still have to lock shared data, and still have to cast to get things to work, so I'm not better off. You can't tell me otherwise, because all this stuff is a figment of your imagination. You have no proof. Until you can show me that I'm better off with an actual example, then I believe we both are equally right :)I didn't think I'd convince anyone the first time around. But I'm patient <g>.
Jul 31 2008
"Walter Bright" wroteSteven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.As described on that page, the problem was fixed with JDK 5, and can be solved using the volatile modifier.Yeah, because all us cowboys don't like your kind. Maybe we need to get us a rope and have a lynchin. Seriously, how can you say that the current threadding tools are 'uncontrolled' (i.e. wild west)?Because of the common multithreaded bug http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html for one example. There is no threading tool I'm aware of that can prevent or detect such bugs.I do too. But I don't see this one being that tool.I spend lots of time thinking about multithreadded issues, and make sure my software works properly. I think the level of quality for threadding issues depends on the coder, not the tools.I believe the tools can make it easier.Are you saying that there will be an automatic notion by the compiler that implements the fences, or that I have to add them on top? If the former, then I don't remember reading that in the article, and that does sound promising.In the case of shared/unshared, it's not going to change anything, except now I have to declare things I didn't have to declare before. I.e. having shared/unshared is going to be just as wild as before.Why? First of all, unshared data isn't going to have sequential or sync issues, by definition. Already, you've cut the problem domain down by a huge chunk. Next, shared data access will come with fences or sync. That isn't going to guarantee no deadlocks, but it will guarantee sequential consistency, and at the very least will dramatically cut the problem domain down.What I'm saying is that if you have to cast just to get something working, you have defeated the system. I'm not saying that you are back to the wild west *by choice*, I'm saying you will most likely end up having to do that just to get it to work. I'm thinking of many cases where you have to use old code, or old libraries that don't have this feature, or code written by someone unaware of the details.Except now instead of the compiler helping you, you have pushed aside that help and said 'I know what I'm doing'. Oops, back to the wild west :)If you want the wild west, you have it, if you want compiler help instead, you got it. How is that worse than C++ or Java, where you always have the wild west and no help at all?How is that possible? shared int *x; void foo(shared int *y) { x = y; } int *x2; void bar() { foo(x2); } After calling bar, isn't x2 now both shared (as x) and unshared at the same time? I think you need casts for both ways. I think shared/unshared is analogous to mutable/invariant. There is no implicit cast.Non-shared can be implicitly cast to shared, as that is always safe. Just not the other way.True, but having it happen implicitly is even worse, because there's no indication that it is happening.dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because the compiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread! But the result is, we're back to the same model as before. And now I have to cast everything. Annoying.All I was saying with that comment is the notion that 'Walter knows best' is not a convincing argument.Please let me decide whether I'm far better off.Ok. D offers both - and for the guy maintaining your code, there'll at least be clear indications of where to look for the source of elusive threading bugs.Optlink currently has a threading bug in it. I have no idea where to look for it in the source code.Threading problems are very difficult to find. I don't think the shared/unshared model will help with that, especially since most likely you will have to break it to get things working. I generally can only find multithreading issues with lots of logging, and running through potentially offending code in my head. I think that this idea has potential, and could possibly lead to something that is helpful. The thinking is in the right direction. But I'm not convinced that this incarnation will be helpful. I'd have to see examples of how this would be useful to understand it better. And please PLEASE make it backwards compatible. I don't see any reason why it must be shared that is the tagged value. -Steve
Aug 01 2008
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article"Walter Bright" wroteI'm hoping that 'shared' will force programmers to think about what they're doing a bit more. A typical multithreaded app should have extremely little shared data. One thing I'm not sure of, though, is if I write a single- threaded app, will I need to label anything shared? Functionally I don't, since having everything thread-local is exactly what I need, but I'm not sure if the compiler will yell at me anyway. I'm guessing it will, which would be a bit annoying, but it would "future proof" the app for adding multithreading later, so perhaps it's okay. SeanSteven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.
Aug 01 2008
"Sean Kelly" wrote== Quote from Steven Schveighoffer articleI'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write. I think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant. -Steve"Walter Bright" wroteI'm hoping that 'shared' will force programmers to think about what they're doing a bit more. A typical multithreaded app should have extremely little shared data. One thing I'm not sure of, though, is if I write a single- threaded app, will I need to label anything shared? Functionally I don't, since having everything thread-local is exactly what I need, but I'm not sure if the compiler will yell at me anyway. I'm guessing it will, which would be a bit annoying, but it would "future proof" the app for adding multithreading later, so perhaps it's okay.Steven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.
Aug 01 2008
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article"Sean Kelly" wroteDarnit, you're right. That's just like 'volatile' in C++. In fact, it's the primary reason why I dislike the const system in D 2.0.== Quote from Steven Schveighoffer articleI'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write."Walter Bright" wroteI'm hoping that 'shared' will force programmers to think about what they're doing a bit more. A typical multithreaded app should have extremely little shared data. One thing I'm not sure of, though, is if I write a single- threaded app, will I need to label anything shared? Functionally I don't, since having everything thread-local is exactly what I need, but I'm not sure if the compiler will yell at me anyway. I'm guessing it will, which would be a bit annoying, but it would "future proof" the app for adding multithreading later, so perhaps it's okay.Steven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.I think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant.You could be right. Though that means yet another label and all the baggage that goes with it. Sean
Aug 01 2008
Steven Schveighoffer Wrote:"Sean Kelly" wrotebut the code there *is* different. there are fence combinations & shit. i guess in such cases you'd need a template.== Quote from Steven Schveighoffer articleI'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write."Walter Bright" wroteI'm hoping that 'shared' will force programmers to think about what they're doing a bit more. A typical multithreaded app should have extremely little shared data. One thing I'm not sure of, though, is if I write a single- threaded app, will I need to label anything shared? Functionally I don't, since having everything thread-local is exactly what I need, but I'm not sure if the compiler will yell at me anyway. I'm guessing it will, which would be a bit annoying, but it would "future proof" the app for adding multithreading later, so perhaps it's okay.Steven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.I think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant.sounds interesting but i don't get it. we have: invariant == never changes const == i won't change it mutable == fuck you, i'm changing in the shared cases we have: unshared == never seen by 2 threads ? == ? shared == fuck you, i'm shared so how would that go. i won't share it? i won't write to it? (that's useless bc of read fences.) anyway this is intriguing shit. unification is power.
Aug 01 2008
== Quote from superdan (super dan.org)'s articlein the shared cases we have: unshared == never seen by 2 threads ? == ? shared == fuck you, i'm shared so how would that go. i won't share it? i won't write to it? (that's useless bc of read fences.) anywaythis is intriguing shit. unification is power. Yeah, the idea of having a unifying label makes some sense, but I haven't been able to figure out what it would mean in terms of behavior. Maybe the middle one would be volatile in that the compiler doesn't optimize use of it but doesn't go so far as to bother with fences? But then the middle ground would be like expert mode, which isn't really what you want. Maybe we're good with just shared and unshared. Sean
Aug 01 2008
Reply to Sean,Yeah, the idea of having a unifying label makes some sense, but I haven't been able to figure out what it would mean in terms of behavior.[...]Maybe we're good with just shared and unshared.The only useful middle ground I see is covered by shared + const (one thread wright, many thread read with whatever else it takes to make that work)
Aug 01 2008
"superdan" wroteSteven Schveighoffer Wrote:The issue I see is that it's not as simple as flipping a switch. If I want to use an object as a shared object, it needs to implement that shared interface now. Might as well code a completely different object. And in that case, can't this just be a library solution (i.e. derive from this object if you want shared access)? You'd probably need to bring volatile back :)I'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write.but the code there *is* different. there are fence combinations & shit. i guess in such cases you'd need a template.I have no idea what the middle ground is :) I'm just saying that without that middle ground, it's going to feel like I'm writing code specifically for sharing or not sharing, and the shared keyword loses a lot of its meaning as a general type modifier. I can't just slap a shared label on anything because that object needs to be specifically written to be a shared object. And in the case of functions which take those objects or data types as parameters, slapping a shared label on something means I have to use a completely different set of functions, which might not exist. If I have to use a library for some reason or another, I might just be tempted to cast away the shared. I might have no other choice. -SteveI think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant.sounds interesting but i don't get it. we have: invariant == never changes const == i won't change it mutable == fuck you, i'm changing in the shared cases we have: unshared == never seen by 2 threads ? == ? shared == fuck you, i'm shared so how would that go. i won't share it? i won't write to it? (that's useless bc of read fences.) anyway this is intriguing shit. unification is power.
Aug 01 2008
Reply to Steven,I have no idea what the middle ground is :) I'm just saying that without that middle ground, it's going to feel like I'm writing code specifically for sharing or not sharing,I stand corrected the middle ground is "don't let me do anything where it matters" No cocreate thing would take on this attribute but references with it could be made from either side.and the shared keyword loses a lot of its meaning as a general type modifier. I can't just slap a shared label on anything because that object needs to be specifically written to be a shared object. And in the case of functions which take those objects or data types as parameters, slapping a shared label on something means I have to use a completely different set of functions, which might not exist. If I have to use a library for some reason or another, I might just be tempted to cast away the shared. I might have no other choice. -Steve
Aug 01 2008
Steven Schveighoffer wrote:"superdan" wroteHopefully the shared data will be encapsulated such that you communicate with it though some lightweight class that converts the pieces that your sharing into something unshared functions can work with. We might then only need a small set of standard lib functions for shared memory which do mostly shared memory specific stuff. However we'll see how things go I guess. -JoelSteven Schveighoffer Wrote:The issue I see is that it's not as simple as flipping a switch. If I want to use an object as a shared object, it needs to implement that shared interface now. Might as well code a completely different object. And in that case, can't this just be a library solution (i.e. derive from this object if you want shared access)? You'd probably need to bring volatile back :)I'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write.but the code there *is* different. there are fence combinations & shit. i guess in such cases you'd need a template.I have no idea what the middle ground is :) I'm just saying that without that middle ground, it's going to feel like I'm writing code specifically for sharing or not sharing, and the shared keyword loses a lot of its meaning as a general type modifier. I can't just slap a shared label on anything because that object needs to be specifically written to be a shared object. And in the case of functions which take those objects or data types as parameters, slapping a shared label on something means I have to use a completely different set of functions, which might not exist. If I have to use a library for some reason or another, I might just be tempted to cast away the shared. I might have no other choice. -SteveI think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant.sounds interesting but i don't get it. we have: invariant == never changes const == i won't change it mutable == fuck you, i'm changing in the shared cases we have: unshared == never seen by 2 threads ? == ? shared == fuck you, i'm shared so how would that go. i won't share it? i won't write to it? (that's useless bc of read fences.) anyway this is intriguing shit. unification is power.
Aug 02 2008
Steven Schveighoffer Wrote:"Walter Bright" wrotei dun think so. first off it's naive to assume that global == shared. no way jose. almost all use of shared data is with heap allocated objects that several threads mess with. agreed there are good cases to share shit in a global. but that is the fringe case. not the usual case. second if you write shared int x then all loads/stores of x are fence protected. i might talk outta my ass but if i understand walt you can't just say y = x or x = 5. you must call some intrinsic shit, for example y = load(x) and store(x, 5). not sure i like that actually. third, the interesting shit starts when you take x's address. the shared quality of x goes with its type so &x is shared(int)*, not int*. i might again talk outta my ass but it looks like the compiler has info to fence all shit properly.Steven Schveighoffer wrote:So if I write: shared int x; As a global variable, how does this help encapsulation? In the current model, if you need shared data, you use global variables. If you don't need shared data, use member or stack variables. My point is that what you will have done is just made the person who wants a global variable write 'shared' in front of it. I don't see how this helps him protect the variable at all. It just seems like you are enforcing something that already can be enforced."Walter Bright" wroteThe idea is that encapsulation is better, and having something shared between everyone violates encapsulation. When you have a global variable 'int x' that everyone can read and write to, and there's a bug, you have the whole program to search for that bug. The principle of encapsulation is that each chunk of data is visible only to the code that needs to see it, and no more.Nearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'here is where you apply my other message. what seems or not to you is zilch. come with facts. real arguments and shit.(Programming languages started out with everything being global data, and has moved away from that ever since.)I'm not advocating using global variables over stack or member variables. All I'm saying is that this 'shared/unshared' model doesn't seem to me like it will eliminate the need for threading constructs, or even help with it.and if you forgot to put volatile your plan is fucked right there. i take issue with c++0x and java 5 equally. they suck shitty goat balls. they *allow* you to write correct code. same as the police allows you to climb mt everest. thank you very much assholes. they do nothing to actually help you with that shit. fuck that shit. if i understand d2 you can't have the dclp bug in d2 even if you tried. the way shit works is you can't have a global that's not shared. if it's shared then the compiler makes it fence protected. if it's fence protected you don't have the dclp bug. problem solved.As described on that page, the problem was fixed with JDK 5, and can be solved using the volatile modifier.Yeah, because all us cowboys don't like your kind. Maybe we need to get us a rope and have a lynchin. Seriously, how can you say that the current threadding tools are 'uncontrolled' (i.e. wild west)?Because of the common multithreaded bug http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html for one example. There is no threading tool I'm aware of that can prevent or detect such bugs.see comment above.I do too. But I don't see this one being that tool.I spend lots of time thinking about multithreadded issues, and make sure my software works properly. I think the level of quality for threadding issues depends on the coder, not the tools.I believe the tools can make it easier.i'm also curious. walt?Are you saying that there will be an automatic notion by the compiler that implements the fences, or that I have to add them on top? If the former, then I don't remember reading that in the article, and that does sound promising.In the case of shared/unshared, it's not going to change anything, except now I have to declare things I didn't have to declare before. I.e. having shared/unshared is going to be just as wild as before.Why? First of all, unshared data isn't going to have sequential or sync issues, by definition. Already, you've cut the problem domain down by a huge chunk. Next, shared data access will come with fences or sync. That isn't going to guarantee no deadlocks, but it will guarantee sequential consistency, and at the very least will dramatically cut the problem domain down.i'd rather break old code than have the shitty model of today. and code written by someone unaware of threading details? you gotta be kidding. i'd erase that code in a second.What I'm saying is that if you have to cast just to get something working, you have defeated the system. I'm not saying that you are back to the wild west *by choice*, I'm saying you will most likely end up having to do that just to get it to work. I'm thinking of many cases where you have to use old code, or old libraries that don't have this feature, or code written by someone unaware of the details.Except now instead of the compiler helping you, you have pushed aside that help and said 'I know what I'm doing'. Oops, back to the wild west :)If you want the wild west, you have it, if you want compiler help instead, you got it. How is that worse than C++ or Java, where you always have the wild west and no help at all?looks like walt has a problem in his hands :))How is that possible? shared int *x; void foo(shared int *y) { x = y; } int *x2; void bar() { foo(x2); } After calling bar, isn't x2 now both shared (as x) and unshared at the same time? I think you need casts for both ways.Non-shared can be implicitly cast to shared, as that is always safe. Just not the other way.True, but having it happen implicitly is even worse, because there's no indication that it is happening.dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because the compiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread! But the result is, we're back to the same model as before. And now I have to cast everything. Annoying.I think shared/unshared is analogous to mutable/invariant. There is no implicit cast.looks the same to me too."steven schveighoffer seems to feel differently" doesn't help either.All I was saying with that comment is the notion that 'Walter knows best' is not a convincing argument.Please let me decide whether I'm far better off.Ok. D offers both - and for the guy maintaining your code, there'll at least be clear indications of where to look for the source of elusive threading bugs.what things would you need to break to get things working.Optlink currently has a threading bug in it. I have no idea where to look for it in the source code.Threading problems are very difficult to find. I don't think the shared/unshared model will help with that, especially since most likely you will have to break it to get things working.I generally can only find multithreading issues with lots of logging, and running through potentially offending code in my head.and that disables d2's premise how.I think that this idea has potential, and could possibly lead to something that is helpful. The thinking is in the right direction. But I'm not convinced that this incarnation will be helpful. I'd have to see examples of how this would be useful to understand it better. And please PLEASE make it backwards compatible. I don't see any reason why it must be shared that is the tagged value.i think you have a basic contradiction here. backward is shit. you just said it. to debug mt shit you need to log and rack your brains and shit. then without missing a beat you go you want to keep all that shit. shit man. if shared is only one iota better i'm all for breaking with the past. the past is a fucking world of pain. let's not forget that.
Aug 01 2008
== Quote from superdan (super dan.org)'s articleSteven Schveighoffer Wrote:That, or 'shared' applies only to the pointer, not to the value being pointed to. However, given the const system I'd be inclined to think that 'shared' may be transitive, in which case yeah, you've got a problem :-) Sean"Walter Bright" wrotelooks like walt has a problem in his hands :))Non-shared can be implicitly cast to shared, as that is always safe. Just not the other way.How is that possible? shared int *x; void foo(shared int *y) { x = y; } int *x2; void bar() { foo(x2); } After calling bar, isn't x2 now both shared (as x) and unshared at the same time? I think you need casts for both ways.
Aug 01 2008
== Quote from Sean Kelly (sean invisibleduck.org)'s article== Quote from superdan (super dan.org)'s articleErr... I spoke too soon. Not a problem because then the value would have to be shared as well. I'd guess this is how it will work. Viral, just like const. SeanSteven Schveighoffer Wrote:That, or 'shared' applies only to the pointer, not to the value being pointed to. However, given the const system I'd be inclined to think that 'shared' may be transitive, in which case yeah, you've got a problem :-)"Walter Bright" wrotelooks like walt has a problem in his hands :))Non-shared can be implicitly cast to shared, as that is always safe. Just not the other way.How is that possible? shared int *x; void foo(shared int *y) { x = y; } int *x2; void bar() { foo(x2); } After calling bar, isn't x2 now both shared (as x) and unshared at the same time? I think you need casts for both ways.
Aug 01 2008
superdan wrote:and if you forgot to put volatile your plan is fucked right there. i take issue with c++0x and java 5 equally. they suck shitty goat balls. they *allow* you to write correct code. same as the police allows you to climb mt everest.I think you put your finger on the problem. The default behavior of C++ and Java is to do the wrong thing. You have to do extra work to do the right thing. D tries to reverse that by making the default the correct thing, and you have to work extra to screw it up.Yes.Are you saying that there will be an automatic notion by the compiler that implements the fences,
Aug 01 2008
Steven Schveighoffer Wrote:shared int *x; void foo(shared int *y) { x = y; } int *x2; void bar() { foo(x2); } After calling bar, isn't x2 now both shared (as x) and unshared at the same time? I think you need casts for both ways. I think shared/unshared is analogous to mutable/invariant. There is no implicit cast.Agree with Steve. There should not be easy casting of pointers. i think cast from not shared int to shared int is good. but int* to shared int* is not good. exactly like with invariant. The new model is very interesting! Good Walter I hoped you have a clever solution like invariant and it looks that you have ^_^. Thank you, Dee Girl
Aug 01 2008
Steven Schveighoffer wrote: <Snip>dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because thecompiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread!But the result is, we're back to the same model as before. And now Ihave to cast everything. Annoying. <Snip> The idea behind compile-time checking like this is that you can quickly identify errors. If someone writes something in a lib you use that is not share safe, you'll know right of the bat. What you want to do with encapsulation is isolate problems at the point at which it occurs, not 5 or 10 classes/functions away when the side effect finally causes weird behavior. With a shared policy you'd be able to encapsulate all shared data to just the parts of the program that use it. That way you have only small set of places to figure out what went wrong. Furthermore it provides a consistent documentation about how a particular object can be used. For example if someone suddenly decides that one of their functions can only work with sharable memory now and your using a non-shared object with it, the compiler will out you when you upgrade that new api and try to compile. If you can't create a shared object or invariant to pass to that function then you dam well better know what your doing. -Joel
Jul 31 2008
"JAnderson" wroteSteven Schveighoffer wrote: <Snip>I believe the direction that this is heading is promising, but my concern is that it actually won't be helpful as currently described. Because I don't think you can implicitly cast shared to unshared and vice versa, you will need to populate your code with casts wherever you cross the boundaries. If this is a lot, then you will end up creating too much noise to be able to find the problems. This model seems equivalent to having mutable and invariant, but not const (the link between). -Stevedmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because thecompiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread!But the result is, we're back to the same model as before. And now Ihave to cast everything. Annoying. <Snip> The idea behind compile-time checking like this is that you can quickly identify errors. If someone writes something in a lib you use that is not share safe, you'll know right of the bat.
Aug 01 2008
Steven Schveighoffer Wrote:"Walter Bright" wroteyou may as well be equally right. or even more right, as you usually are. sure you are a great hacker who knows threads in and out, as "you spend a lot of time thinking about multithreaded issues". i'm impressed. i do suggest you run a lil experiment one day tho. google for walter bright. figure out what kinds of shit he's done. google for bartosz milewski. figure out for what kinds of shit he's done. google for andrei alexanderescu. figure out for what kinds of shit he's done. then google for steven schveighoffer. unless sure enough you are hans boehm in disguise. then ask yourself. "is my big mouth going to make up for all this?"Steven Schveighoffer wrote:I have no idea where you came up with this. To me global means shared. Global means the world can see it, meaning that it's shared between all. Even VB.net uses 'Shared' as the keyword to mean 'global'"Walter Bright" wroteNearly all global data is assumed to be and treated as if it were unshared. So making unshared the default is the right solution. And frankly, if you're using a lot of global variables, you might want to reevaluate what you're doing. Lots of global variables is the 80's style of programming :-)http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data.Yeah, because all us cowboys don't like your kind. Maybe we need to get us a rope and have a lynchin. Seriously, how can you say that the current threadding tools are 'uncontrolled' (i.e. wild west)? I spend lots of time thinking about multithreadded issues, and make sure my software works properly. I think the level of quality for threadding issues depends on the coder, not the tools. In the case of shared/unshared, it's not going to change anything, except now I have to declare things I didn't have to declare before. I.e. having shared/unshared is going to be just as wild as before. I may be wrong, and this shared/unshared thing will be really great for people. But I think it needs a lot of work before it's helpful. In its current incarnation, I'll call it the 'shared wild west' approach :PI would hazard to guess that adopting this would cause a larger rift than const.Perhaps. But the alternative is the current wild west approach to multithreaded programming. With the proliferation of multicore computers, the era where this is acceptable is coming to an end.Except now instead of the compiler helping you, you have pushed aside that help and said 'I know what I'm doing'. Oops, back to the wild west :)Second, the fact that you can't implicitly cast shared to unshared and vice versa. It's going to make communication between both 'worlds' very error prone, as you will be required to cast for any call from one to the other.I think the reverse is true. Moving data between those worlds is dangerous and needs to be carefully vetted, so requiring an explicit cast will reduce the chance of this happening unintentionally.dmd mycode.d Error: when calling foo(shared int *), cannot pass int * edit mycode.d, cast to shared int * OK, now it works :) Probably without any problems, because the compiler has no idea whether I'm going to change it in another thread. Hell, I might not even HAVE more than one thread! But the result is, we're back to the same model as before. And now I have to cast everything. Annoying.People will do this just to get their code to work, without thinking about the consequences.True, but having it happen implicitly is even worse, because there's no indication that it is happening.Please let me decide whether I'm far better off. I don't need protection from stuff that doesn't matter. I will still have to lock shared data, and still have to cast to get things to work, so I'm not better off. You can't tell me otherwise, because all this stuff is a figment of your imagination. You have no proof. Until you can show me that I'm better off with an actual example, then I believe we both are equally right :) -SteveEven those that do think about the consequences, can't have the compiler statically check the cast in either direction, so once you cast, you lose all the benefit.But still, you're far better off than the current wild west approach where everything is implicitly shared with no protection whatsoever. The popular double checked locking bug will be impossible to code in D without stuffing in explicit casts. The casts will be a red flag that the programmer is making a mistake.
Jul 31 2008
"superdan" wroteyou may as well be equally right. or even more right, as you usually are. sure you are a great hacker who knows threads in and out, as "you spend a lot of time thinking about multithreaded issues". i'm impressed. i do suggest you run a lil experiment one day tho. google for walter bright. figure out what kinds of shit he's done. google for bartosz milewski. figure out for what kinds of shit he's done. google for andrei alexanderescu. figure out for what kinds of shit he's done. then google for steven schveighoffer. unless sure enough you are hans boehm in disguise. then ask yourself. "is my big mouth going to make up for all this?"Just because I'm not published all over google doesn't mean I don't know anything. Your artistic use of the english language combined with bullying tactics doesn't really phase me, as I care nothing about ego. So go right ahead and bitch about what I don't know :) Last I heard, this is a public forum, and I'm free to question Walter and his team as much as I want. I can't believe you pulled the "do you know who I am" card for Walter :) What do I get if I google for superdan? http://www.youtube.com/watch?v=uLLk42PcM9I -Steve
Aug 01 2008
Steven Schveighoffer Wrote:"superdan" wrotethanks for keeping ur cool. really appreciate that. my intent was not to bully you and shit. this is programming. it's not entomology. anybody who's somebody in programming *is* on the web somewhere for the web is nerdworld. some participation to an open source project. some blog. some article they've written. that's what i see all around. but i still agree. sometimes you can know your shit without being published. you work for nasa, cia, or some secretive hedge fund. or you just don't like sharing shit. no problem. but without a track record you must come with real good *factual* shit to be credible. not "i spend a lot of time thinking about this shit". not what you believe. without a proven track record nobody gives a shit on how you spend your nights or on what you believe. so as long as you stick to facts u should be in good shape. if you come with "my opinion is" shit then you should understand nobody will give a shit. in fact they will give a negative shit because that further fucks your credibility. as an example of good factual shit is your point that nonshared -> shared should not be implicit. now you're talking. i'll think about that shit too. insofar as this being a public forum. i'm a prime abuser of that with my shitfucking and shit. but that is nothing compared to the technical abuse this forum has seen and still does. if that goes down i'd be happy to get my shitfucking shit down too.you may as well be equally right. or even more right, as you usually are. sure you are a great hacker who knows threads in and out, as "you spend a lot of time thinking about multithreaded issues". i'm impressed. i do suggest you run a lil experiment one day tho. google for walter bright. figure out what kinds of shit he's done. google for bartosz milewski. figure out for what kinds of shit he's done. google for andrei alexanderescu. figure out for what kinds of shit he's done. then google for steven schveighoffer. unless sure enough you are hans boehm in disguise. then ask yourself. "is my big mouth going to make up for all this?"Just because I'm not published all over google doesn't mean I don't know anything. Your artistic use of the english language combined with bullying tactics doesn't really phase me, as I care nothing about ego. So go right ahead and bitch about what I don't know :) Last I heard, this is a public forum, and I'm free to question Walter and his team as much as I want. I can't believe you pulled the "do you know who I am" card for Walter :)What do I get if I google for superdan? http://www.youtube.com/watch?v=uLLk42PcM9I -Stevesweet :)
Aug 01 2008
"superdan" wroteSteven Schveighoffer Wrote:I probably have more hits under schveiguy than Steven Schveighoffer. But I don't really write articles. I wrote one for topcoder when I was into that (about threading coincidentally)."superdan" wrotethanks for keeping ur cool. really appreciate that. my intent was not to bully you and shit. this is programming. it's not entomology. anybody who's somebody in programming *is* on the web somewhere for the web is nerdworld. some participation to an open source project. some blog. some article they've written. that's what i see all around.you may as well be equally right. or even more right, as you usually are. sure you are a great hacker who knows threads in and out, as "you spend a lot of time thinking about multithreaded issues". i'm impressed. i do suggest you run a lil experiment one day tho. google for walter bright. figure out what kinds of shit he's done. google for bartosz milewski. figure out for what kinds of shit he's done. google for andrei alexanderescu. figure out for what kinds of shit he's done. then google for steven schveighoffer. unless sure enough you are hans boehm in disguise. then ask yourself. "is my big mouth going to make up for all this?"Just because I'm not published all over google doesn't mean I don't know anything. Your artistic use of the english language combined with bullying tactics doesn't really phase me, as I care nothing about ego. So go right ahead and bitch about what I don't know :) Last I heard, this is a public forum, and I'm free to question Walter and his team as much as I want. I can't believe you pulled the "do you know who I am" card for Walter :)but i still agree. sometimes you can know your shit without being published. you work for nasa, cia, or some secretive hedge fund. or you just don't like sharing shit. no problem. but without a track record you must come with real good *factual* shit to be credible. not "i spend a lot of time thinking about this shit". not what you believe. without a proven track record nobody gives a shit on how you spend your nights or on what you believe.What I meant by that is, I think possibly the only solution for multithreadded issues is careful planning, training, and experience. In otherwords, my threading code works because I pay careful attention to the threading details. It might be impossible for a technical solution to exist to prevent Joe Newb programmer from making threading mistakes.so as long as you stick to facts u should be in good shape. if you come with "my opinion is" shit then you should understand nobody will give a shit. in fact they will give a negative shit because that further fucks your credibility.You don't have to believe me. Nobody has to believe me. The fact that I stated my opinion is good enough for me. If I turn out to be right, then people might listen to me next time. If I turn out to be wrong, then it still won't stop me from stating my opinion on the next issue. Mind, I can't say anything about facts because I don't have any. I'm very careful to state things in terms of what "I think", and "my opinion". I don't have any more facts than Walter and company to know whether this concept will be useful. All I can say is what I think might happen (as is all Walter can say too). If it turns out to be the best thing since transitive const, then I'm all for it. Remember that Walter and company had several iterations before they got that right. I think that will probably be the case here too.insofar as this being a public forum. i'm a prime abuser of that with my shitfucking and shit. but that is nothing compared to the technical abuse thisforum has seen and still does. if that goes down i'd be happy to get my shitfucking shit down too. I don't know what 'shitfucking' is, but it sounds very unpleasant :) -Steve
Aug 01 2008
Steven Schveighoffer Wrote:"superdan" wrotenow yer talking. keep on doing that.Steven Schveighoffer Wrote:I probably have more hits under schveiguy than Steven Schveighoffer. But I don't really write articles. I wrote one for topcoder when I was into that (about threading coincidentally)."superdan" wrotethanks for keeping ur cool. really appreciate that. my intent was not to bully you and shit. this is programming. it's not entomology. anybody who's somebody in programming *is* on the web somewhere for the web is nerdworld. some participation to an open source project. some blog. some article they've written. that's what i see all around.you may as well be equally right. or even more right, as you usually are. sure you are a great hacker who knows threads in and out, as "you spend a lot of time thinking about multithreaded issues". i'm impressed. i do suggest you run a lil experiment one day tho. google for walter bright. figure out what kinds of shit he's done. google for bartosz milewski. figure out for what kinds of shit he's done. google for andrei alexanderescu. figure out for what kinds of shit he's done. then google for steven schveighoffer. unless sure enough you are hans boehm in disguise. then ask yourself. "is my big mouth going to make up for all this?"Just because I'm not published all over google doesn't mean I don't know anything. Your artistic use of the english language combined with bullying tactics doesn't really phase me, as I care nothing about ego. So go right ahead and bitch about what I don't know :) Last I heard, this is a public forum, and I'm free to question Walter and his team as much as I want. I can't believe you pulled the "do you know who I am" card for Walter :)and you're implying that it can't be done any better. you know, if everybody thought like you there'd be no progress. i read napoleon's biography a while ago. one smart motherfucker that was. he really could do two things at the same time. i could only go as far as chew gum and fart. anyway there was this general of his. forgot his name. call him general mofo. so at austerlitz napoleon says let's do this and that. mofo comes back: "if i were you i'd do this and that". napoleon says: "that's why you are mofo and i'm fucking napoleon". i might've added a word in the quote somewhere :) i was working at intel. there's this layout program that would take forfuckingever on a design i'd given it. so during lunch i'm like, "what a fucking piece of shit this layout algo is." and a new coworker smiles and says "i know. i designed it." he was kind enough to explain what problems he'd overcome. like heuristics on np complete shit. i don't even know exactly what that is. sure enough, when it's done his program did a layout i couldn't imagine in a brazillion years. these guys operate at a different level. and as far as walter or bartosz are concerned i'm a pathetic loser. at least i'm glad when i can appreciate a good idea if i see it. and the more it goes about how i feel it can't be done, the better the idea. at least with time i learned not to come all cocky and shit with stuff i don't grok.but i still agree. sometimes you can know your shit without being published. you work for nasa, cia, or some secretive hedge fund. or you just don't like sharing shit. no problem. but without a track record you must come with real good *factual* shit to be credible. not "i spend a lot of time thinking about this shit". not what you believe. without a proven track record nobody gives a shit on how you spend your nights or on what you believe.What I meant by that is, I think possibly the only solution for multithreadded issues is careful planning, training, and experience. In otherwords, my threading code works because I pay careful attention to the threading details. It might be impossible for a technical solution to exist to prevent Joe Newb programmer from making threading mistakes.doesn't work that way dewd. it's like crying wolf whenever you feel it in your urine. open the cabbage patches. then the mind. then the piehole. that's how it works. i read this thread stuff yesterday a few times. my first reaction was it's useless. second reaction was it's restrictive as shit. third read i thought they might be up to something. and it was the interaction with invariant that brought it all home for me. most importantly i didn't shout my piehole around after the first read.so as long as you stick to facts u should be in good shape. if you come with "my opinion is" shit then you should understand nobody will give a shit. in fact they will give a negative shit because that further fucks your credibility.You don't have to believe me. Nobody has to believe me. The fact that I stated my opinion is good enough for me. If I turn out to be right, then people might listen to me next time. If I turn out to be wrong, then it still won't stop me from stating my opinion on the next issue.Mind, I can't say anything about facts because I don't have any. I'm very careful to state things in terms of what "I think", and "my opinion". I don't have any more facts than Walter and company to know whether this concept will be useful. All I can say is what I think might happen (as is all Walter can say too). If it turns out to be the best thing since transitive const, then I'm all for it. Remember that Walter and company had several iterations before they got that right. I think that will probably be the case here too.my point is you (and me too) have less facts, less experience, less smarts, and less intuition than walt & co. if we tell them about a mistake, fine. but if we go with "i feel shit" that's not progress. it's good you compare with the const shit. that's the most fucking awesome thing about d2. if you asked me before i would've told you nobody can pull that shit and live. more over. walt has got a shitstorm the size of fucking china when he got it wrong. if i were walt i would've given up. but that's why walt is walt he kept at it and pushed the shit through. what pisses me off is that to this day people still bitch about const while refusing to actually understand it. it's not even hard. first understand. then bitch.
Aug 01 2008
superdan wrote:i read napoleon's biography a while ago. one smart motherfucker that was. he really could do two things at the same time. i could only go as far as chew gum and fart. anyway there was this general of his. forgot his name. call him general mofo. so at austerlitz napoleon says let's do this and that. mofo comes back: "if i were you i'd do this and that". napoleon says: "that's why you are mofo and i'm fucking napoleon". i might've added a word in the quote somewhere :)Do you believe that General McAuliffe really said "nuts" at the Battle of the Bulge? I don't. <g>
Aug 01 2008
Walter Bright Wrote:superdan wrote:let's see. four-words expletive too strong for the american public. sure it was "poop" :) can't think of bastogne without thinking of BoB. what an awesome movie that is.i read napoleon's biography a while ago. one smart motherfucker that was. he really could do two things at the same time. i could only go as far as chew gum and fart. anyway there was this general of his. forgot his name. call him general mofo. so at austerlitz napoleon says let's do this and that. mofo comes back: "if i were you i'd do this and that". napoleon says: "that's why you are mofo and i'm fucking napoleon". i might've added a word in the quote somewhere :)Do you believe that General McAuliffe really said "nuts" at the Battle of the Bulge? I don't. <g>
Aug 01 2008
superdan wrote:My father met the man and asked him. The actual word rhymes with "spit". I'm amused by the people who think a GI would really use the word "nuts".Do you believe that General McAuliffe really said "nuts" at the Battle of the Bulge? I don't. <g>let's see. four-words expletive too strong for the american public. sure it was "poop" :) can't think of bastogne without thinking of BoB. what an awesome movie that is.
Aug 01 2008
"superdan" wroteSteven Schveighoffer Wrote:I'm not saying that we shouldn't try. I'm just saying it *might* be impossible. I encourage Walter to solve it, but I can't see how this solution does it. Look into NP-complete. It's a set of problems that nobody can write a program to solve it (efficiently anyways). First one I ever heard of is the traveling salesman problem: http://en.wikipedia.org/wiki/Traveling_salesman_problem"superdan" wroteand you're implying that it can't be done any better. you know, if everybody thought like you there'd be no progress.but i still agree. sometimes you can know your shit without being published. you work for nasa, cia, or some secretive hedge fund. or you just don't like sharing shit. no problem. but without a track record you must come with real good *factual* shit to be credible. not "i spend a lot of time thinking about this shit". not what you believe. without a proven track record nobody gives a shit on how you spend your nights or on what you believe.What I meant by that is, I think possibly the only solution for multithreadded issues is careful planning, training, and experience. In otherwords, my threading code works because I pay careful attention to the threading details. It might be impossible for a technical solution to exist to prevent Joe Newb programmer from making threading mistakes.I admit that I already knew this shared/unshared was coming :) So I already had thought about it over a month ago, but I wasn't allowed to talk about it on the NG. But I'm a little disappointed that it's no different than the version I saw before... Bottom line, I did think about it before posting. Quite a bit.doesn't work that way dewd. it's like crying wolf whenever you feel it in your urine. open the cabbage patches. then the mind. then the piehole. that's how it works. i read this thread stuff yesterday a few times. my first reaction was it's useless. second reaction was it's restrictive as shit. third read i thought they might be up to something. and it was the interaction with invariant that brought it all home for me. most importantly i didn't shout my piehole around after the first read.so as long as you stick to facts u should be in good shape. if you come with "my opinion is" shit then you should understand nobody will give a shit. in fact they will give a negative shit because that further fucks your credibility.You don't have to believe me. Nobody has to believe me. The fact that I stated my opinion is good enough for me. If I turn out to be right, then people might listen to me next time. If I turn out to be wrong, then it still won't stop me from stating my opinion on the next issue.Hey, don't listen to me. Nobody has to do what I say based on a feeling. But I'm sure as hell not going to accept that if Walter feels good about it, it must be right, any more than you won't accept what I say because I don't feel good about it. I need proof. And the burden of proof is on Walter. I've already written multithreadded programs with the current D system, and they work. You need to convince me that this new way will work more than just "Trust me, you'll be better off".Mind, I can't say anything about facts because I don't have any. I'm very careful to state things in terms of what "I think", and "my opinion". I don't have any more facts than Walter and company to know whether this concept will be useful. All I can say is what I think might happen (as is all Walter can say too). If it turns out to be the best thing since transitive const, then I'm all for it. Remember that Walter and company had several iterations before they got that right. I think that will probably be the case here too.my point is you (and me too) have less facts, less experience, less smarts, and less intuition than walt & co. if we tell them about a mistake, fine. but if we go with "i feel shit" that's not progress.it's good you compare with the const shit. that's the most fucking awesome thing about d2. if you asked me before i would've told you nobody can pull that shit and live. more over. walt has got a shitstorm the size of fucking china when he got it wrong. if i were walt i would've given up. but that's why walt is walt he kept at it and pushed the shit through. what pisses me off is that to this day people still bitch about const while refusing to actually understand it. it's not even hard. first understand. then bitch.I am one of those that fully understands the const system, and I still think it is missing some pieces :) Every proposal I've made to fill in those pieces on the NG and to Andrei directly ultimately results in a response like "yes that looks like a sound idea, and would work, but we *feel* that it would make people like const less, so we're not going to implement it." I love a lot of what Walter and Andrei have done, but when ideas are shot down due to a perception of what might happen in the future, it seems to be based a lot less on fact than I would like. -Steve
Aug 01 2008
Steven Schveighoffer wrote:"Walter Bright" wrote<Snip> As far as radical changes to the language breaking existing code, if Walter maintained that approach D would never beable to make radical and correct improvements (rather then half-work rounds). We would end up with C++. This is why we have D 1 and 2. D 2 is still the experimental branch. Yes it makes radical changes however D might never be able to provide better multi-threading support if it can't make breaking changes. My option is that the experimental branch of D should be correct first and backwoods compatible second. Having said that. I don't think this shared approach should be added to the language until const is sorted because that should provide a kinda proof of concept for the syntactics of shared memory. <Snip>http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data. I would hazard to guess that adopting this would cause a larger rift than const.-Steve
Jul 31 2008
"JAnderson" wroteSteven Schveighoffer wrote:So should people wait to write libraries until all this is fleshed out? I mean, there is already a pretty significant code base that assumes shared is the default. When this ever gets around to being implemented (and released), how much work will it be to rewrite all code to either use a new model, or put a shared tag on every variable? It seems to me the logical approach is to assume shared and tag things as unshared."Walter Bright" wrote<Snip> As far as radical changes to the language breaking existing code, if Walter maintained that approach D would never beable to make radical and correct improvements (rather then half-work rounds). We would end up with C++. This is why we have D 1 and 2. D 2 is still the experimental branch. Yes it makes radical changes however D might never be able to provide better multi-threading support if it can't make breaking changes.http://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data. I would hazard to guess that adopting this would cause a larger rift than const.My option is that the experimental branch of D should be correct first and backwoods compatible second.That is a great recipe for the forking of D :) I'm not saying that breaking changes should be unacceptable, I'm just saying that there better be a really compelling reason to break things. I believe Walter's view of "wild west" programming is completely off target. Many good multithreadded applications exist today, without the aid of this shared/unshared view. I don't see how having this is going to magically solve any threadding issues. If anything it's going to just pop up as an annoying obstacle that is frequently bypassed with casts, making the system useless anyways. I don't know if this can be shown until the idea moves from theory to practice, so maybe we'll just have to wait and see. This could be a stepping stone to a really great system, just like the first const incarnations were awful, but the one we have now (save a few missing pieces) is pretty good. Just my opinion. -Steve
Jul 31 2008
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article"JAnderson" wrotelibd forked the language and is far better for it. Tango has avoided this route because our primary goal is to provide a library for D. This seems to have turned out to be "provide a library for D 1.0" however, given the lack of support for certain programming methodologies in D 2.0 that Tango uses pervasively, as you're no doubt aware :-) This leaves Tango in a bit of a pickle, since it means either changing Tango or forking D if we ever want to move past D 1.0.My option is that the experimental branch of D should be correct first and backwoods compatible second.That is a great recipe for the forking of D :) I'm not saying that breaking changes should be unacceptable, I'm just saying that there better be a really compelling reason to break things.I believe Walter's view of "wild west" programming is completely off target. Many good multithreadded applications exist today, without the aid of this shared/unshared view. I don't see how having this is going to magically solve any threadding issues. If anything it's going to just pop up as an annoying obstacle that is frequently bypassed with casts, making the system useless anyways. I don't know if this can be shown until the idea moves from theory to practice, so maybe we'll just have to wait and see. This could be a stepping stone to a really great system, just like the first const incarnations were awful, but the one we have now (save a few missing pieces) is pretty good.Systems programming is the low-down dirtiest part of the Wild West, too. It's a realm where programmers do all sorts of things that a general applications programmer would be canned for, because it's necessary and because they *do* know what they're doing. I am very much concerned that the "future of D" is as a general applications language and that its systems language roots will be left to rot. And who needs another applications language, anyway? The world has a million of them. Sean
Jul 31 2008
Sean Kelly:I am very much concerned that the "future of D" is as a general applications language and that its systems language roots will be left to rot. And who needs another applications language, anyway? The world has a million of them.I think D is already partially unfit for being a system language, the runtime memory footprint is large; here it's compared with Free Pascal: http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=dlang&lang2=fpascal The GC can be disabled, but you have to carry it around in the executable anyway. The size of the executables produced by DMD is large compared to the exes you obtain from stripped C. At the moment you can't run such things on sytems with little RAM, as you can do with C. Regarding the hard real time systems, I think people there are scared of a GC (even if in practice it's not a problem). So at the moment there are many things you can do with C that are a problem to do with D. Bye, bearophile
Jul 31 2008
== Quote from bearophile (bearophileHUGS lycos.com)'s articleSean Kelly:compared with Free Pascal:I am very much concerned that the "future of D" is as a general applications language and that its systems language roots will be left to rot. And who needs another applications language, anyway? The world has a million of them.I think D is already partially unfit for being a system language, the runtime memory footprint is large; here it'shttp://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=dlang&lang2=fpascalAgreed. This is largely related to the generated TypeInfo, and is somewhat annoying.The GC can be disabled, but you have to carry it around in the executable anyway. The size of the executablesproduced by DMD is large compared to the exes you obtain from stripped C. At the moment you can't run such things on sytems with little RAM, as you can do with C. It's actually possible to create a D application that doesn't have a GC at all. Tango even supports this out of the box. The downside is that some language features rely on the existence of a GC and won't work properly without one. AAs are one example, and string concatenation is another. However, a sufficiently diligent programmer could just not use these features, or the runtime could be modified to explicitly support a GC-less application by making different assumptions about what happens to discarded memory, etc.Regarding the hard real time systems, I think people there are scared of a GC (even if in practice it's not a problem).So at the moment there are many things you can do with C that are a problem to do with D. There are soft real-time GCs. In fact, I believe there are hard real-time GCs as well--the Metronome project at IBM springs to mind. I would love to see such a GC for D, but I don't have the time and am also not certain that it's possible to make a hard real-time conservative GC (which D currently requires). I would be inclined to think that such a GC would be incremental and thus require more comprehensive type info, but I haven't given the topic enough thought to be certain about that. All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite. Sean
Jul 31 2008
Sean Kelly Wrote:All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite.i agree. std.algorithm i sleep with under my pillow. but std.xml. what a sick piece of shit that is. if they tried to make it slow on purpose they couldn't have succeeded better. std.xml must go.
Jul 31 2008
superdan wrote:Sean Kelly Wrote:Heh. Want to have some fun, take a look at std.zip. Then realize that, unless you unpack every member every time, the members you didn't unpack will still have their compressed data overwritten by a compressed version of the expanded data (which is ""). Then weep. --downs, immensely glad the zip archive he noticed this on was backed up in SVN.All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite.i agree. std.algorithm i sleep with under my pillow. but std.xml. what a sick piece of shit that is. if they tried to make it slow on purpose they couldn't have succeeded better. std.xml must go.
Aug 01 2008
downs wrote:Heh. Want to have some fun, take a look at std.zip. Then realize that, unless you unpack every member every time, the members you didn't unpack will still have their compressed data overwritten by a compressed version of the expanded data (which is ""). Then weep. --downs, immensely glad the zip archive he noticed this on was backed up in SVN.Please file this with bugzilla, or even better, a patch!
Aug 01 2008
Sean Kelly:All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation.I agree, in many D programs I have found that avoiding memory allocations can speed up the code 5-15 times. You can see the last time I have seen that in this thread: But Java HotSpot shows that a good GC can make fast enough many programs that allocate memory often (but they often need 4-10 times more RAM). Bye, bearophile
Jul 31 2008
Sean Kelly wrote:All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite.I wrote a version of Empire (the game) in D that does no allocation at all. Therefore, the gc never runs and there is never any unbounded delay. The gc is never going to pop up out of nowhere and sink your application. A gc only happens when you request memory from the gc. For the real time constrained section of code, the idea is to pre-allocate all the data you'll need first, then do no allocation within the critical section. In fact, such critical code in C++ does this anyway because there are no bounded time constraints on C++ new either. C malloc has no bound constraints, either.
Jul 31 2008
Walter Bright wrote:Sean Kelly wrote:This is true, new in C++ can seriously degrade performance if not manage properly. However calling a couple of 100 smallish news in C++ per frame is quite acceptable and has a infindecimal affect on performance, when working on windows. D however is another kettle of fish. You can't have any allocations during the active part of the game. You have to do it all a load points. Why? Because at some point the memory allocator will runout of free memory and then it will need to clear anything that's unused. Normally this wouldn't be a problem however it takes over a frame to flush; and that leads to a very noticeable stutter. Now I haven't tried realtime programming with allocations in the realtime part for a while so things might have changed however that's how it was the last time I was playing around with that stuff. Also I haven't tried Tangos. Also nedmalloc can give a huge performance boost to windows allocation making it almost as good as preallocations. Sometimes its better due to memory locality which reduce cache misses. The great thing about D's GC though its that other people can implement there own. I hope that when someone comes up with a really good one and it will become part of the main distribution (ie not become another windows malloc mess). -JoelAll that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite.I wrote a version of Empire (the game) in D that does no allocation at all. Therefore, the gc never runs and there is never any unbounded delay. The gc is never going to pop up out of nowhere and sink your application. A gc only happens when you request memory from the gc. For the real time constrained section of code, the idea is to pre-allocate all the data you'll need first, then do no allocation within the critical section. In fact, such critical code in C++ does this anyway because there are no bounded time constraints on C++ new either. C malloc has no bound constraints, either.
Jul 31 2008
JAnderson wrote:Walter Bright wrote:I should point out that I'm aware of fragmentation however you can still call new's in either a way that doesn't fragment, or simply rely on paging to fix the problem. If your not creating a program that needs to run longer then a month (ie maybe your game has a maximum time limit of 30 minutes or something) then the problem is even less of an issue. If you are, make sure you understand fragmentation.Sean Kelly wrote:This is true, new in C++ can seriously degrade performance if not manage properly. However calling a couple of 100 smallish news in C++ per frame is quite acceptable and has a infindecimal affect on performance, when working on windows.All that said, I believe it's entirely possible to write performance-critical code in D so long as the programmer is careful about memory allocation. And as Walter has said before, because even malloc is not time-constrained the same goes for any use of dynamic memory--GCs just magnify the issue. Server apps in Tango, for example, don't allocate any memory at all once initialization is complete. This is why they tend to be so blisteringly fast. It's also why Tango is designed the way it is--not always super-convenient for run of the mill apps programming, but quite scalable for high-end work. By contrast, I'd argue that Phobos is the opposite.I wrote a version of Empire (the game) in D that does no allocation at all. Therefore, the gc never runs and there is never any unbounded delay. The gc is never going to pop up out of nowhere and sink your application. A gc only happens when you request memory from the gc. For the real time constrained section of code, the idea is to pre-allocate all the data you'll need first, then do no allocation within the critical section. In fact, such critical code in C++ does this anyway because there are no bounded time constraints on C++ new either. C malloc has no bound constraints, either.D however is another kettle of fish. You can't have any allocations during the active part of the game. You have to do it all a load points. Why? Because at some point the memory allocator will runout of free memory and then it will need to clear anything that's unused. Normally this wouldn't be a problem however it takes over a frame to flush; and that leads to a very noticeable stutter. Now I haven't tried realtime programming with allocations in the realtime part for a while so things might have changed however that's how it was the last time I was playing around with that stuff. Also I haven't tried Tangos. Also nedmalloc can give a huge performance boost to windows allocation making it almost as good as preallocations. Sometimes its better due to memory locality which reduce cache misses. The great thing about D's GC though its that other people can implement there own. I hope that when someone comes up with a really good one and it will become part of the main distribution (ie not become another windows malloc mess). -Joel
Jul 31 2008
== Quote from bearophile (bearophileHUGS lycos.com)'s articleSean Kelly:memory footprint is large; here it's compared with Free Pascal:I am very much concerned that the "future of D" is as a general applications language and that its systems language roots will be left to rot. And who needs another applications language, anyway? The world has a million of them.I think D is already partially unfit for being a system language, the runtimehttp://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=dlang&lang2=fpascalThe GC can be disabled, but you have to carry it around in the executableanyway. The size of the executables produced by DMD is large compared to the exes you obtain from stripped C. At the moment you can't run such things on sytems with little RAM, as you can do with C.Regarding the hard real time systems, I think people there are scared of a GC(even if in practice it's not a problem). So at the moment there are many things you can do with C that are a problem to do with D.Bye, bearophileA few things: First of all, Pascal is from the Stone Age and therefore has had a chance to be optimized in every way feasible to make it as tight as humanly possible. DMD is a reference implementation of a relatively immature language, and right now the focus is on adding more features and fixing bugs, not on aggressive space optimization. Maybe once the dust settles a little, the GC can optionally be made a shared DLL, or excluded outright if the programmer is going to disable it anyhow, and optimizations can be added to make it more space-efficient. Second: I actually think D is a great application programming language that fills a pretty useful niche. I am a computational biologist, so my needs are basically performance, correctness and ease of use. If I wrote everything in C, C++ or (I almost don't even want to say it) Fortran, I'd never get anything done because these are such crufty old languages that are much more difficult to use than D. shoved down my throat where it makes the least sense, namely small but performance-critical projects. If I used Python or Ruby, the performance penalty would just be ridiculous unless I wrote some parts in C, in which case...uh, I kind of wanted to avoid using old-school, low-level languages. Bottom line is, D gives me most of the ease of use of a high-level dynamic language and most of the performance of C or C++, and for what I do that seems like a very good tradeoff.
Jul 31 2008
dsimcha wrote:Bottom line is, D gives me most of the ease of use of a high-level dynamic language and most of the performance of C or C++, and for what I do that seems like a very good tradeoff.Couldn't agree more. --downs
Jul 31 2008
dsimcha:A few things: First of all, Pascal is from the Stone Age and therefore has had a chance to be optimized in every way feasible to make it as tight as humanly possible.Yet, we're talking about a pretty modern ObjectPascal here, with a syntax quite close to the Delphi one. I have used it, and it's a good language, you can write tons of things with it, and it's way different from the C language, it has many nice modern things, and very little pointers, it's plenty fast, the IDEs are good, etc, but I understand your point and I agree. I know that D is young, etc, and if you follow this group you probably know that I like D.Second: I actually think D is a great application programming language that fills a pretty useful niche. I am a computational biologist, so my needs are basically performance, correctness and ease of use.I too use D mostly for bioinformatics, I have introduced it (with Python, well Python first) in my lab that so far has used mostly Perl/Fortran/C. And I too like to use D for such purposes, sometimes Python is too much slow, and I don't want to use Cython much because for me programming in D is much simpler than keeping track of the mad reference counts in Cython programs. (But I think such purposes of D aren't exactly the same you may want from a system language this thread was talking about, you too talk about 'application programming language'). Bye, bearophile
Jul 31 2008
"Steven Schveighoffer" wrote"Walter Bright" wroteAfter thinking about this some more, I realize that this part of my argument is wrong. I was thinking since by default you can share data today, that should be the default. But most of the time, you declare things (global or otherwise) expecting them not to be shared. Shared data is usually wrapped in an object that you can synchronize on. So most existing code should work fine unless that code expects to share data with other threads. That being said, I still see issues with casting and with function calling. -Stevehttp://www.reddit.com/comments/6u7k0/sharing_in_d/There are 2 problems I see with this scheme. First, that the default is 'unshared'. This is going to break a lot of existing code, and make peoples lives miserable who do not want to deal with unshared non-stack data. I would hazard to guess that adopting this would cause a larger rift than const.
Aug 01 2008
Walter Bright wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/I have also posted it on my new news site http://crowdnews.eu -- Crowdnews.eu - Promote yourself and your friends!
Jul 30 2008
If I understand it correctly, then you are going down the right path with this stuff. IMO, the ultimate goal is a programming language that is thread-safe by default, just as a GC language is memory-safe by default. I sounds like you may need to flesh things out quite a bit to attain a comprehensive solution for thread safety. Keep in mind, there should always be ways to subvert safety when necessary for performance. -Craig
Jul 31 2008
Craig Black wrote:If I understand it correctly, then you are going down the right path with this stuff. IMO, the ultimate goal is a programming language that is thread-safe by default, just as a GC language is memory-safe by default.You aren't the first to note the analogy to GC!I sounds like you may need to flesh things out quite a bit to attain a comprehensive solution for thread safety. Keep in mind, there should always be ways to subvert safety when necessary for performance.Of course - casting a shared type to unshared means subverting any compiler guarantees, just like when const is cast away.
Jul 31 2008
Walter Bright Wrote:Craig Black wrote:yeh i could swear i read an article about that. was his name grosh or so? interesting shit that was. i finally read bartosz' stuff. the basic idea looks cool. i bet there will be much kinks to work out tho. fwiw perl does similar shit in one of its many attempts at threads. aside from being slow like molasses in the winter the model is clean. problem is perl must duplicate a lot more shit than d has. so things stand good for d. pooling will help a ton too.If I understand it correctly, then you are going down the right path with this stuff. IMO, the ultimate goal is a programming language that is thread-safe by default, just as a GC language is memory-safe by default.You aren't the first to note the analogy to GC!
Jul 31 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articlehttp://www.reddit.com/comments/6u7k0/sharing_in_d/Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D), plus some language checking on top of that. I'll admit to being somewhat concerned that the checking aspect will incur an unwanted runtime expense, as I don't believe there's any way at compile-time to detect that a variable is being accessed by multiple threads. One could try to assert that non-shared data may never be used in synchronized blocks, but not all data used in such blocks is actually shared. In short, I'd love a "thread" storage class, as always, and would be curious to see how the rest turns out. It sounds unlikely to work, but who knows. That said, data can be shared in one of two ways: either it may be referenced via a static or global variable or it may be explicitly passed between two threads. The latter case is typically safe because it's deliberate while the former may well not be. Thus, the easiest way to get all this working would be to forbid the use of "static" in a multithreaded app, or add checking to "static" so it acts like "shared." That eliminates the need for a new keyword and makes existing apps all compile correctly by default. The final step would be to require that all static functions either be atomic or contain a "synchronized" statement. Easy to do at compile-time and it would get the job done for the most part. It's too bad we've been unable to talk about any of this offline. We've been considering doing a lot of this sort of thing with Tango for years now but had been avoiding any unnecessary runtime changes in hopes that it would increase the likelihood that the powers that be would get involved. Obviously, that idea failed :-) But I'll take this as implicit permission to have at it, since you seem to be talking along roughly similar lines for D2 anyway. Sean
Jul 31 2008
Sean Kelly wrote:Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D),It's actually implemented in D 2.0 as the __thread storage class, however it's for testing purposes only.plus some language checking on top of that. I'll admit to being somewhat concerned that the checking aspect will incur an unwanted runtime expense, as I don't believe there's any way at compile-time to detect that a variable is being accessed by multiple threads.It's done statically by the type - a shared type can be accessed by multiple types, an unshared type cannot.It's too bad we've been unable to talk about any of this offline. We've been considering doing a lot of this sort of thing with Tango for years now but had been avoiding any unnecessary runtime changes in hopes that it would increase the likelihood that the powers that be would get involved. Obviously, that idea failed :-) But I'll take this as implicit permission to have at it, since you seem to be talking along roughly similar lines for D2 anyway.We've been talking about doing it as a static type system, not as a runtime one. Bartosz mentioned that there are ways to do it at runtime, but there are a lot of issues that would need to be worked out for that.
Jul 31 2008
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleSean Kelly wrote:Yeah, I saw that. If only it were in D 1.0 :-)Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D),It's actually implemented in D 2.0 as the __thread storage class, however it's for testing purposes only.What about this: shared ClassA a; void main() { ClassB b = a.getB(); b.mutate(); } I'd imagine the checking will catch common mistakes but not issues like the above? Or will the fact that 'b' is being returned from a require the declaration of 'b' to be shared because the value may be accessed by both ClassA and anything outside ClassA? Seanplus some language checking on top of that. I'll admit to being somewhat concerned that the checking aspect will incur an unwanted runtime expense, as I don't believe there's any way at compile-time to detect that a variable is being accessed by multiple threads.It's done statically by the type - a shared type can be accessed by multiple types, an unshared type cannot.
Jul 31 2008
Sean Kelly wrote:== Quote from Walter Bright (newshound1 digitalmars.com)'s article1.0 has tools.threads' TLS!(), so you can use that :) It works under win32 and posix. </tools_ad> --downsSean Kelly wrote:Yeah, I saw that. If only it were in D 1.0 :-)Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D),It's actually implemented in D 2.0 as the __thread storage class, however it's for testing purposes only.
Aug 01 2008
"downs" <default_357-line yahoo.de> wrote in message news:g6ufic$1hj4$2 digitalmars.com...Sean Kelly wrote:You do realize (1) you're advertising to one of the main Tango devs, and (2) Tango already has thread-local storage.== Quote from Walter Bright (newshound1 digitalmars.com)'s article1.0 has tools.threads' TLS!(), so you can use that :) It works under win32 and posix. </tools_ad> --downsSean Kelly wrote:Yeah, I saw that. If only it were in D 1.0 :-)Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D),It's actually implemented in D 2.0 as the __thread storage class, however it's for testing purposes only.
Aug 01 2008
Jarrett Billingsley wrote:"downs" <default_357-line yahoo.de> wrote in message news:g6ufic$1hj4$2 digitalmars.com...Um. Well, yeah, I realize that _now_ :) Sorry for that misunderstanding.Sean Kelly wrote:You do realize (1) you're advertising to one of the main Tango devs, and (2) Tango already has thread-local storage.== Quote from Walter Bright (newshound1 digitalmars.com)'s article1.0 has tools.threads' TLS!(), so you can use that :) It works under win32 and posix. </tools_ad> --downsSean Kelly wrote:Yeah, I saw that. If only it were in D 1.0 :-)Sounds like the addition of a thread-local storage class (which I've been asking for since I discovered D),It's actually implemented in D 2.0 as the __thread storage class, however it's for testing purposes only.
Aug 01 2008
Sean Kelly wrote:What about this: shared ClassA a; void main() { ClassB b = a.getB(); b.mutate(); } I'd imagine the checking will catch common mistakes but not issues like the above? Or will the fact that 'b' is being returned from a require the declaration of 'b' to be shared because the value may be accessed by both ClassA and anything outside ClassA?Shared cannot be implicitly cast to unshared. Just like const cannot be implicitly cast to mutable.
Aug 01 2008
Walter Bright wrote:Shared cannot be implicitly cast to unshared. Just like const cannot be implicitly cast to mutable.But you can implicitly cast unshared to shared, right?
Aug 07 2008
"Russell Lewis" wroteWalter Bright wrote:No. There is no implicit casting or else you can have data that is shared and unshared at the same time. It will be up to the coder to ensure only one is happening at a time. -SteveShared cannot be implicitly cast to unshared. Just like const cannot be implicitly cast to mutable.But you can implicitly cast unshared to shared, right?
Aug 07 2008
Steven Schveighoffer wrote:"Russell Lewis" wroteYeah, I saw your (was it you?) example of how that would become problematic. Did you see my "scope locks" idea as a possible way to safely move data between the shared & unshared realms?Walter Bright wrote:No. There is no implicit casting or else you can have data that is shared and unshared at the same time. It will be up to the coder to ensure only one is happening at a time.Shared cannot be implicitly cast to unshared. Just like const cannot be implicitly cast to mutable.But you can implicitly cast unshared to shared, right?
Aug 07 2008
"Russell Lewis" wroteSteven Schveighoffer wrote:I think there may be no middle ground, as in order for locks to work, every access to a locked variable must be through the lock. If you have 2 references to a variable, one that is shared and one that is not, locking on the shared variable does nothing to prevent the unshared variable from being accessed without the lock. I think the middle ground simply needs to do the most safe thing (i.e. treat as shared), but not allow implicit casting to unshared or shared. However, in this case, you incur a possible performance hit when it might not be necessary. It might be that the middle ground is simply undesirable, so you have to do explicit casting. I'm not sure. -Steve"Russell Lewis" wroteYeah, I saw your (was it you?) example of how that would become problematic. Did you see my "scope locks" idea as a possible way to safely move data between the shared & unshared realms?Walter Bright wrote:No. There is no implicit casting or else you can have data that is shared and unshared at the same time. It will be up to the coder to ensure only one is happening at a time.Shared cannot be implicitly cast to unshared. Just like const cannot be implicitly cast to mutable.But you can implicitly cast unshared to shared, right?
Aug 08 2008
Steven Schveighoffer wrote:I think there may be no middle ground, as in order for locks to work, every access to a locked variable must be through the lock. If you have 2 references to a variable, one that is shared and one that is not, locking on the shared variable does nothing to prevent the unshared variable from being accessed without the lock. I think the middle ground simply needs to do the most safe thing (i.e. treat as shared), but not allow implicit casting to unshared or shared. However, in this case, you incur a possible performance hit when it might not be necessary. It might be that the middle ground is simply undesirable, so you have to do explicit casting.I think that you misunderstood my locking idea. My idea was that there was only one root reference to a variable, and you have to grab the lock to get to it. So you can treat it as unshared while you hold the lock (with all the performance benefits, and code conveniences like ++, that you get with unshared data) but while you do not hold the lock it is absolutely inaccessible. Put more explicitly, a "locked" variable has three modes: shared, in accessible to all locked in read mode, unshared const scope to one thread locked in write mode, unshared scope to one thread Of course, you can't have external pointers pointing into the data structure (from outside the lock), but inside the lock it's perfectly OK to have pointers to other things inside the lock (or to external shared data). So you could, for instance, build a doubly-linked list; you just make the sure that your global variable, which points to the head of the list, is declared as "locked".
Aug 08 2008
On Thu, 31 Jul 2008 04:52:16 +0400, Walter Bright <newshound1 digitalmars.com> wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/Hello, volatile! :)
Jul 31 2008
Walter Bright Wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant. Allowing access to thread-local globals is a bad idea.
Jul 31 2008
Jason House wrote:Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.Allowing access to thread-local globals is a bad idea.Why? Global thread local storage is even enshrined into C++0x.
Jul 31 2008
Walter Bright Wrote:Jason House wrote:looks 2 me more like more of the confusion in yesterthread.Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.99% of the global shit i ever defined i wanted to be thread local. i had to take special measures to make it so. dealing with globals in one thread is shitty to boot. using globals to communicate across threads is sheer suicide.Allowing access to thread-local globals is a bad idea.Why? Global thread local storage is even enshrined into C++0x.
Jul 31 2008
superdan wrote:Walter Bright Wrote:What about cases that depend on external resources, like a global buffer object for HTTP downloads? In that case you want cached results to be available to as many threads as possible, especially if the respective server has a high latency. --downsJason House wrote:looks 2 me more like more of the confusion in yesterthread.Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.99% of the global shit i ever defined i wanted to be thread local. i had to take special measures to make it so. dealing with globals in one thread is shitty to boot. using globals to communicate across threads is sheer suicide.Allowing access to thread-local globals is a bad idea.Why? Global thread local storage is even enshrined into C++0x.
Aug 01 2008
== Quote from downs (default_357-line yahoo.de)'s articlesuperdan wrote:take special measures to make it so.Walter Bright Wrote:Jason House wrote:looks 2 me more like more of the confusion in yesterthread.Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.99% of the global shit i ever defined i wanted to be thread local. i had toAllowing access to thread-local globals is a bad idea.Why? Global thread local storage is even enshrined into C++0x.communicate across threads is sheer suicide.dealing with globals in one thread is shitty to boot. using globals toWhat about cases that depend on external resources, like a global buffer objectfor HTTP downloads?In that case you want cached results to be available to as many threads aspossible, especially if the respective server has a high latency. Yup. This is pretty much the only time I use globals in my apps-- if there's some huge data structure I want to reference in all my threads. A user list... something like that. In a language like Erlang, that user list would probably be managed by a distinct process and would serve requests from other processes that wanted to perform operations on it. Without shared data in D I'd do pretty much the same thing. All D would need is a solid messaging system. libd has one built-in, but we avoided this with Tango because it would effectively change the language. Sean
Aug 01 2008
On Wed, 30 Jul 2008 17:52:16 -0700, Walter Bright wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/I haven't done much threading, so this sounds mostly good. On question I have relates to when a single threaded program/component is using libraries designed to support multithreading (thus it asks for a shared value). You aren't really doing any sharing you just wanted to call the function for what it does. Would this never happen? Do I now have to cast my unshared to shared even though I'm not interested in sharing? My main point, is that if I'm writing a single threaded program, I shouldn't care about sharing even if the library I'm using does.
Jul 31 2008
Jesse Phillips wrote:Would this never happen? Do I now have to cast my unshared to shared even though I'm not interested in sharing? My main point, is that if I'm writing a single threaded program, I shouldn't care about sharing even if the library I'm using does.Unshared can be implicitly cast to shared, so you shouldn't have to.
Jul 31 2008
Walter Bright Wrote:Unshared can be implicitly cast to shared, so you shouldn't have to.That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory. Two, the guarantees for shared data are lost. Code using the non-shared reference will not respect that the variable really is shared.
Aug 01 2008
Jason House wrote:Walter Bright Wrote:True, but the memory allocation system shouldn't be (and isn't) built that way.Unshared can be implicitly cast to shared, so you shouldn't have to.That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.Two, the guarantees for shared data are lost. Code using the non-shared reference will not respect that the variable really is shared.That would be true if shared were implicitly cast to unshared, but that's not the case. It's unshared implicitly cast to shared.
Aug 01 2008
Walter Bright Wrote:Jason House wrote:Let's say I have an object that was originally written assuming non-shared access and contains one member function with no arguments. Some later coder comes by and decides it'd be nice to share this object among threads and creates a shared instance of it. There's no way to know if calling the member function is safe. Maybe it accesses a non-shared global variable. Maybe a call to an encapsulated object's member function uses a non-shared global variable. The maintainer must be extremely careful and scour the code to ensure there's no accidental sharing that was not intended. Maybe I'm reading too much into stuff again, but the article did say "The proposal is to make accidental sharing impossible".Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.
Aug 01 2008
"Jason House" wroteWalter Bright Wrote:I have a feeling that the shared/unshared comes with a requriement for 'shared' functions. That is, in order to call a function on an object that is 'shared', you have to call a function where the 'this' pointer is shared: class C { shared f(); // can call on a shared C instance, means the 'this' pointer is shared f(); // can call on an unshared C instance } -SteveJason House wrote:Let's say I have an object that was originally written assuming non-shared access and contains one member function with no arguments. Some later coder comes by and decides it'd be nice to share this object among threads and creates a shared instance of it. There's no way to know if calling the member function is safe. Maybe it accesses a non-shared global variable. Maybe a call to an encapsulated object's member function uses a non-shared global variable. The maintainer must be extremely careful and scour the code to ensure there's no accidental sharing that was not intended. Maybe I'm reading too much into stuff again, but the article did say "The proposal is to make accidental sharing impossible".Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.
Aug 01 2008
Steven Schveighoffer Wrote:"Jason House" wroteI'd much prefer to discuss the problematic use case and either confirming or rejecting that D will help protect against it. Your definition implies that such programming errors will not be caught. This seems against the spirit of the article.Walter Bright Wrote:I have a feeling that the shared/unshared comes with a requriement for 'shared' functions. That is, in order to call a function on an object that is 'shared', you have to call a function where the 'this' pointer is shared: class C { shared f(); // can call on a shared C instance, means the 'this' pointer is shared f(); // can call on an unshared C instance } -SteveJason House wrote:Let's say I have an object that was originally written assuming non-shared access and contains one member function with no arguments. Some later coder comes by and decides it'd be nice to share this object among threads and creates a shared instance of it. There's no way to know if calling the member function is safe. Maybe it accesses a non-shared global variable. Maybe a call to an encapsulated object's member function uses a non-shared global variable. The maintainer must be extremely careful and scour the code to ensure there's no accidental sharing that was not intended. Maybe I'm reading too much into stuff again, but the article did say "The proposal is to make accidental sharing impossible".Walter Bright Wrote:Pure doesn't apply to data types, it applies to functions. I don't know what you mean.http://www.reddit.com/comments/6u7k0/sharing_in_d/This is one of my 3 big wishes for the D language. The artical talks about shared being transitive just like const/invariant. I certainly hope it's more like pure than transitive invariant.
Aug 01 2008
Steven Schveighoffer wrote:I have a feeling that the shared/unshared comes with a requriement for 'shared' functions. That is, in order to call a function on an object that is 'shared', you have to call a function where the 'this' pointer is shared:That's right. Shared objects can only call shared or synchronized methods.
Aug 01 2008
Walter Bright Wrote:Jason House wrote:I don't see how memory allocation fits into it. It's about deallocation and garbage collection. I believe the single-threaded garbage collection would only scan memory for the thread in question and would miss shared data's reference to non-shared data.Walter Bright Wrote:True, but the memory allocation system shouldn't be (and isn't) built that way.Unshared can be implicitly cast to shared, so you shouldn't have to.That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.I don't see how having one thread with a reference to unshared data and N threads with shared references to the unshared data can work. Maybe the shared references will play nice with each other, but they will mess up assumptions by the unshared code. What am I missing?Two, the guarantees for shared data are lost. Code using the non-shared reference will not respect that the variable really is shared.That would be true if shared were implicitly cast to unshared, but that's not the case. It's unshared implicitly cast to shared.
Aug 01 2008
== Quote from Jason House (jason.james.house gmail.com)'s articleWalter Bright Wrote:the single-threaded garbage collection would only scan memory for the thread in question and would miss shared data's reference to non-shared data. I think the only way this can work is if you make 'shared' a bit like 'pure' in that a shared object can't reference non-shared data. Then you have a full-on "stop the world" GC for the shared data area. With this approach you'd at least know that most of your GC cycles would be thread-local, which is better than none of them. If the user wants to bypass this they can always cast unshared to shared when assigning a shared reference to it. This gets back to what I said about shared being transitive. The sticky part would be enforcing it--I guess you'd have to do so at the point of assignment: class C { int* x; shared void put( int* y ) { x = y; // error, y is not "shared(int*)" } } It really is a lot like const, isn't it? SeanJason House wrote:I don't see how memory allocation fits into it. It's about deallocation and garbage collection. I believeWalter Bright Wrote:True, but the memory allocation system shouldn't be (and isn't) built that way.Unshared can be implicitly cast to shared, so you shouldn't have to.That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.
Aug 01 2008
Sean Kelly wrote:== Quote from Jason House (jason.james.house gmail.com)'s articleMy thought was you could use Ref counting for shared memory and mark and sweep for unshared. -JoelWalter Bright Wrote:the single-threaded garbage collection would only scan memory for the thread in question and would miss shared data's reference to non-shared data. I think the only way this can work is if you make 'shared' a bit like 'pure' in that a shared object can't reference non-shared data. Then you have a full-on "stop the world" GC for the shared data area. With this approach you'd at least know that most of your GC cycles would be thread-local, which is better than none of them. If the user wants to bypass this they can always cast unshared to shared when assigning a shared reference to it. This gets back to what I said about shared being transitive. The sticky part would be enforcing it--I guess you'd have to do so at the point of assignment: class C { int* x; shared void put( int* y ) { x = y; // error, y is not "shared(int*)" } } It really is a lot like const, isn't it? SeanJason House wrote:I don't see how memory allocation fits into it. It's about deallocation and garbage collection. I believeWalter Bright Wrote:True, but the memory allocation system shouldn't be (and isn't) built that way.Unshared can be implicitly cast to shared, so you shouldn't have to.That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.
Aug 02 2008
JAnderson Wrote:My thought was you could use Ref counting for shared memory and mark and sweep for unshared.That's a really good idea. Mark and sweep (as currently implemented in D) can be very expensive with multiple threads.
Aug 02 2008
Jason House wrote:JAnderson Wrote:Thanks, A couple more thoughts. With a naive approach a lock would have to be acquired every time something was referenced counted in the unshared. There are 2 ways I can think of to counter this: 1) Have a thread local ref count. Then the shared memory would simply have a ref count of the number threads that have access to that piece of memory. When the memory is first required it would acquire a lock and increment the count in the shared as well as the local. From then on it would only increment/decrement its local ref count until it reached 0 then it would have to update the shared one again. 2) The local thread doesn't contain a ref count but instead has a proxy memory for each shared memory reference. When it goes to delete the proxy it tells the shared memory to dec its count. 3) Perhaps ref counting isn't need after all. All that is really needed is a table in the shared memory that simply details what threads have what pieces of memory. When the shared GC runs it will also go over that list and see that some pieces of memory are still being held on to. Local threads would only need to lock/unlock that portion of memory. The shared GC would no be ableble to run while this memory is being accessed. The advantage here is that each thread has its own bit of memory in the shared to work with. Of course race conditions will still be a problem to solve. -JoelMy thought was you could use Ref counting for shared memory and mark and sweep for unshared.That's a really good idea. Mark and sweep (as currently implemented in D) can be very expensive with multiple threads.
Aug 02 2008
Steven Schveighoffer Wrote:I'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write.Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.I think at the very least, for this to be palatable, there needs to be another modifier that unifies shared and unshared. Similar to how const unifies mutable and invariant.Shared unifies shared and unshared.
Aug 01 2008
"Walter Bright" wroteSteven Schveighoffer Wrote:I'm assuming you read my previous example, but I'll rewrite it to demonstrate what I'm trying to show: class sharedObj { private int *_x; synchronized shared int x() {return *_x;} synchronized shared int x(int y) {*_x = y;} synchronized shared void rebind(shared int *y) {_x = y;} } shared sharedObj obj; static this() { obj = new sharedObj; } int *x2; void bar() { obj.x = x2; *x2 = 3; // is this supposed to be guaranteed safe? } Now, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean. I was under the impression that 'unshared' means 'lock free', which cannot be enforcable if you can implicitly cast away the 'lock free' aspect of it. ??? -SteveI'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write.Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.
Aug 01 2008
Steven Schveighoffer Wrote:"Walter Bright" wroteUh oh Steve, you're starting to sound like me! I made the 2^n comment in the context of the const system a while back and now you're looking at how globals might break a transitve data type system... I could have sworn you were the loudest voice against my ideas!Steven Schveighoffer Wrote:I'm assuming you read my previous example, but I'll rewrite it to demonstrate what I'm trying to show: class sharedObj { private int *_x; synchronized shared int x() {return *_x;} synchronized shared int x(int y) {*_x = y;} synchronized shared void rebind(shared int *y) {_x = y;} } shared sharedObj obj; static this() { obj = new sharedObj; } int *x2; void bar() { obj.x = x2; *x2 = 3; // is this supposed to be guaranteed safe? } Now, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean. I was under the impression that 'unshared' means 'lock free', which cannot be enforcable if you can implicitly cast away the 'lock free' aspect of it. ??? -SteveI'm thinking more in the case of functions. If I have a function foo, and I want to pass my shared data version to it, I need to re-implement foo with the parameters as being shared. Imagine a function with several parameters, in which you want to pass a combination of shared/unshared. That's 2^n variations you have to write.Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.
Aug 01 2008
Steven Schveighoffer wrote:Now, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean.Eh, I think you've got me there. Looks like unshared cannot be implicitly converted to shared.
Aug 01 2008
Walter Bright wrote:Steven Schveighoffer wrote:Akin to why const cannot be implicitly converted to invariant, no? -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DNow, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean.Eh, I think you've got me there. Looks like unshared cannot be implicitly converted to shared.
Aug 11 2008
One thing that recently popped into my mind about the shared/unshared discussion: What about arrays, etc that are manipulated by multiple threads, but in such a way that each thread is guaranteed not to touch the same elements as any other thread, and to never reallocate the array? This is something I actually do, for such things as filling in large matrices. If I understand this proposal correctly, if the array is unshared, multiple threads can't touch it. If it is shared, the compiler will automatically make it synchronized. In this case, the synchronization overhead might be large and unnecessary. If I have each thread write to separate, unshared data structures and merge them together later, then I'm adding needless complexity to my code.
Aug 11 2008
dsimcha:What about arrays, etc that are manipulated by multiple threads, but in such a way that each thread is guaranteed not to touch the same elements as any other thread, and to never reallocate the array?If you take a slice of an array [a..b] you don't copy data, so if threads can work on adjacent parts you can slice it in parts that are unshared, and then use the whole usliced block of data... Bye, bearophile
Aug 11 2008
== Quote from dsimcha (dsimcha yahoo.com)'s articleOne thing that recently popped into my mind about the shared/unshared discussion: What about arrays, etc that are manipulated by multiple threads, but in such a way that each thread is guaranteed not to touch the same elements as any other thread, and to never reallocate the array? This is something I actually do, for such things as filling in large matrices. If I understand this proposal correctly, if the array is unshared, multiple threads can't touch it. If it is shared, the compiler will automatically make it synchronized. In this case, the synchronization overhead might be large and unnecessary. If I have each thread write to separate, unshared data structures and merge them together later, then I'm adding needless complexity to my code.For arrays with elements smaller than the bus width or for unaligned arrays there are still word tearing issues, which makes such an approach risky at best. Less importantly, depending on the size and alignment of the array the threads could end up all competing for the same cache line, which would render parallelization of the algorithm largely pointless unless the computation is extremely expensive. It's almost always better to have each thread work on a copy of the data and then merge it later. Sean
Aug 11 2008
Walter Bright Wrote:Shared unifies shared and unshared.It seems that you want the semantics for shared to be ``allocated on either the shared heap or the local heap'' and for non-shared to be ``allocated on a thread local heap''. Is that right? If so, then it seems the only safe cast is from non-shared to *const* shared. I think that was what Steven's example was meant to demonstrate (though I had trouble following it).
Aug 01 2008
Walter Bright Wrote:http://www.reddit.com/comments/6u7k0/sharing_in_d/When can we expect to see this in D2? For the first time since moving to Tango, I'm considering moving back to Phobos. A monolithic garbage collector kills scalability for my data intensive application. Of couse all interesting hardware is 64 bit, so I may need to be more patient...
Aug 04 2008
Jason House Wrote:When can we expect to see this in D2? For the first time since moving to Tango, I'm considering moving back to Phobos.It'll come in stages. For example, D 2.0 already supports thread local storage for globals. Next will probably come the 'sharing' type constructor, and name mangling. All this will phase in over the next 3 months or so.l
Aug 04 2008