August 20, 2004
In article <cg59uu$gfi$1@digitaldaemon.com>, Walter says...
>
>"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:cg4b8t$1pd$2@digitaldaemon.com...
>> Question: what's the purpose of using "volatile" in various places. Since,
>AFAIK, D's volatile speaks to intra-thread
>> memory coherence, and do not cross-thread contention, aren't these
>superfluous? Or have you come across some secret
>> wisdom? (If so, send it to me quickly, via the secret T1!)
>
>D's volatile has essentially nothing in common with C's, and everything to do with helping with writing multithreaded apps. I learned about it from Scott Meyer's talk on multithreading. As I recall, it was about preventing the compiler from moving loads and stores across locks. C++ has no such guarantee, although C++ optimizers in reality respect the locks. This is the modern understanding of volatile, and both Java and C# have altered their definitions of volatile to suit as well.

Yup.  Andrei and Scott co-wrote articles in the July and August editions of DDJ about this ("C++ and the Perils of Double-Checked Locking").  There was also a thread about it in comp.std.c++.  It all boils down to the evil of the "as-if" rule.


Sean


August 20, 2004
In article <cg5jfh$lr9$1@digitaldaemon.com>, Walter says...
>
>
>"antiAlias" <fu@bar.com> wrote in message news:cg5i6n$l3k$1@digitaldaemon.com...
>> That's the difference between the Java/C++ and D implementation. The
>former
>> tag the variable itself, while D tags the usage. I think the D approach to the "memory-barrier" thing is the 'correct' one, but it may lead to obtuse and hard-to-find bugs. For instance, you have to manually and carefully
>add
>> the volatile tag to each usage, rather than the compiler doing it for you (in the Java/C++ case). D, however, gives you more flexibility and control over how/where the barrier is applied. I think that's accurate ... someone please correct me if I'm wrong.
>
>I think you've got it right.

It might be nice to also offer a way to separate acquire/release semantics for folks who care.  I can't think of a clean way to do this offhand, but perhaps:

volatile(acquire)
volatile(release)


Sean


August 20, 2004
"Walter" <newshound@digitalmars.com> wrote in message news:cg59uu$gfi$1@digitaldaemon.com...
>
> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:cg4b8t$1pd$2@digitaldaemon.com...
> > Question: what's the purpose of using "volatile" in various places. Since,
> AFAIK, D's volatile speaks to intra-thread
> > memory coherence, and do not cross-thread contention, aren't these
> superfluous? Or have you come across some secret
> > wisdom? (If so, send it to me quickly, via the secret T1!)
>
> D's volatile has essentially nothing in common with C's, and everything to do with helping with writing multithreaded apps. I learned about it from Scott Meyer's talk on multithreading. As I recall, it was about preventing the compiler from moving loads and stores across locks. C++ has no such guarantee, although C++ optimizers in reality respect the locks. This is the modern understanding of volatile, and both Java and C# have altered their definitions of volatile to suit as well.

Ok.

But I'll need you to fine-grain some examples for me before that coallesces into a genuine understanding.

Maybe we can do this in written form somewhere soon? ;)


August 20, 2004
"antiAlias" <fu@bar.com> wrote in message news:cg5i6n$l3k$1@digitaldaemon.com...
> "Matthew"  wrote ...
> > I don't think we're going to be able to keep it in the same format for
> DTL, though. If you don't mind, I'd rather keep
> > the container implementations as consistent as possible, in terms of
> layout, etc., so I'd be looking to reformat it
> > considerably.
> >
> > Obviously there'll be deeper changes as well, such as templatisation, and
> incorporation of the composable range
> > transformations/filters.
>
> Sure ... edit with aplomb  <g>

Thanks, though I suspect it'll be more rotten plum than aplomb, but I'll do my best.

> > Question: what's the purpose of using "volatile" in various places. Since,
> AFAIK, D's volatile speaks to intra-thread
> > memory coherence, and do not cross-thread contention, aren't these
> superfluous? Or have you come across some secret
> > wisdom? (If so, send it to me quickly, via the secret T1!)
>
> That's the difference between the Java/C++ and D implementation. The former tag the variable itself, while D tags the usage. I think the D approach to the "memory-barrier" thing is the 'correct' one, but it may lead to obtuse and hard-to-find bugs. For instance, you have to manually and carefully add the volatile tag to each usage, rather than the compiler doing it for you (in the Java/C++ case). D, however, gives you more flexibility and control over how/where the barrier is applied. I think that's accurate ... someone please correct me if I'm wrong.

>
>
> >
> > Matthew
> >
> > "antiAlias" <fu@bar.com> wrote in message
> news:cg48q9$ma$1@digitaldaemon.com...
> > > No problem. Just pull it out of the (browser enabled) dsource.org
> > > repository. The documentation needs a wee bit of attention :~)
> > >
> > > Let's share updates (on that module) until we get some resolution on how
> to
> > > easily resolve multiple interdependent libraries ...
> > >
> > >
> > > "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:cg42kq$2ubh$1@digitaldaemon.com...
> > > >
> > > > "antiAlias" <fu@bar.com> wrote in message
> > > news:cg41s8$2u61$1@digitaldaemon.com...
> > > > > Walter" <newshound@digitalmars.com> wrote in message
> > > > > > 2.0. BTW, are you following Andrei A's thread on adding lock-free
> > > > > concurrent
> > > > > > containers to C++? It's a great read in comp.lang.c++.moderated
> under
> > > the
> > > > > > thread "Multithreaded programming: is the C++ standardization
> > > committee
> > > > > > listening?"
> > > > >
> > > > > About time too! On that note, mango.cache has a port of Doug Lea's latest-and-greatest concurrent HashMap. Nice,clean, concise bit of
> code,
> > > > > configurable (contention-level) and very efficient: no read-locks at
> > > all.
> > > > > Also has foreach() support. I suggest this migrate into one of the
> > > container
> > > > > libs rather than slumbering quietly within Mango.
> > > >
> > > > We'll get that one into DTL, if you don't mind. :)
> > > >
> > > >
> > >
> > >
> >
> >
>
>


August 20, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:cg5ran$qvc$1@digitaldaemon.com...
> In article <cg5jfh$lr9$1@digitaldaemon.com>, Walter says...
> >
> >
> >"antiAlias" <fu@bar.com> wrote in message news:cg5i6n$l3k$1@digitaldaemon.com...
> >> That's the difference between the Java/C++ and D implementation. The
> >former
> >> tag the variable itself, while D tags the usage. I think the D approach to the "memory-barrier" thing is the 'correct' one, but it may lead to obtuse and hard-to-find bugs. For instance, you have to manually and carefully
> >add
> >> the volatile tag to each usage, rather than the compiler doing it for you (in the Java/C++ case). D, however, gives you more flexibility and control over how/where the barrier is applied. I think that's accurate ... someone please correct me if I'm wrong.
> >
> >I think you've got it right.
>
> It might be nice to also offer a way to separate acquire/release semantics for folks who care.  I can't think of a clean way to do this offhand, but perhaps:
>
> volatile(acquire)
> volatile(release)

Can we do block volatile, as in:

    volatile
    {
        ...
    }

Is that even meaningful?



August 20, 2004
In article <cg5tje$sdr$3@digitaldaemon.com>, Matthew says...
>
>
>"Sean Kelly" <sean@f4.ca> wrote in message news:cg5ran$qvc$1@digitaldaemon.com...
>> In article <cg5jfh$lr9$1@digitaldaemon.com>, Walter says...
>> >
>> >
>> >"antiAlias" <fu@bar.com> wrote in message news:cg5i6n$l3k$1@digitaldaemon.com...
>> >> That's the difference between the Java/C++ and D implementation. The
>> >former
>> >> tag the variable itself, while D tags the usage. I think the D approach to the "memory-barrier" thing is the 'correct' one, but it may lead to obtuse and hard-to-find bugs. For instance, you have to manually and carefully
>> >add
>> >> the volatile tag to each usage, rather than the compiler doing it for you (in the Java/C++ case). D, however, gives you more flexibility and control over how/where the barrier is applied. I think that's accurate ... someone please correct me if I'm wrong.
>> >
>> >I think you've got it right.
>>
>> It might be nice to also offer a way to separate acquire/release semantics for folks who care.  I can't think of a clean way to do this offhand, but perhaps:
>>
>> volatile(acquire)
>> volatile(release)
>
>Can we do block volatile, as in:
>
>    volatile
>    {
>        ...
>    }
>
>Is that even meaningful?

volatile is a statement specifier, so yes.  Is it meaningful?  I think it could be.  Memory barriers are far cheaper than locks but they aren't free.  I think a volatile block would basically put an acquire barrier at the beginning of the block and a release barrier at the end.  This would basically say that "this block of code can not be reordered with respect to the surrounding code" though I think the code *within* the block could still be reordered.  Perhaps this last bit is something Walter could answer?

For the record, I *think* this is a correct implementation of the DCLP in D:

# class Singleton
# {
#     static Singleton s;
#
#     Singleton instance()
#     {
#         volatile Singleton tmp = s;
#         if(!tmp)
#         {
#            synchronized
#            {
#                tmp = s;
#                if(!tmp)
#                {
#                   volatile tmp = new Singleton();
#                   s = tmp;
#                }
#            }
#         }
#         return s;
#     }
# }

With the above, the block volatile might be useful if we wanted to do extra initialization of the singleton before assigning to s, thus replacing:

# volatile tmp = new Singleton();

with:

# volatile {
#    tmp = new Singleton();
#    // do stuff
# }


Sean


August 20, 2004
You'll forgive me Sean, but the double-locking 'style' was driven out of Java developers after it was shown to be mostly futile (I think it may have been Doug Lea who demonstrated that). The recommended approach over there is to construct singletons statically; which is where a 'static final' assignment would be really useful in D:

static final Whatever singleton = new Whatever (...);

I know you've run into this need before. For those who don't know, the D approach is thus:

static Whatever singleton;

static this()
{
    singleton = new Whatever (...);
}

Would be nice to have the former syntactic-sugar; but I imagine it would add the same compiler complexity as static-constructors do, in terms of figuring out the interdependencies across multiple related 'static final' assignments.

Which leads to a question: how does the compiler deal with circular dependencies across static-constructors? Let's try it out ...

class A
{
        static B b;

        static this()
        {
                printf ("A\n");
                b = new B;
        }
}

class B
{
        static A a;

        static this()
        {
                printf ("B\n");
                a = new A;
        }
}

Note that I wouldn't recommend this as a practice to anyone, but it may
occur accidentally where multiple modules are involved (I've done that with
Mango). No compile errors ~ emits:
A
B

In fact, the only obvious means to get the output in a different order is to
switch the class order within the file; that is, placing B above A yields:
B
A

Is there no dependency checking done for static constructors? Is this a bug? Am I being particularly dense today?

n.b. the documentation for static constructors is apparently out-of-date.




"Sean Kelly" <sean@f4.ca> wrote in message news:cg5uva$t06$1@digitaldaemon.com...
> volatile is a statement specifier, so yes.  Is it meaningful?  I think it
could
> be.  Memory barriers are far cheaper than locks but they aren't free.  I
think a
> volatile block would basically put an acquire barrier at the beginning of
the
> block and a release barrier at the end.  This would basically say that
"this
> block of code can not be reordered with respect to the surrounding code"
though
> I think the code *within* the block could still be reordered.  Perhaps
this last
> bit is something Walter could answer?
>
> For the record, I *think* this is a correct implementation of the DCLP in
D:
>
> # class Singleton
> # {
> #     static Singleton s;
> #
> #     Singleton instance()
> #     {
> #         volatile Singleton tmp = s;
> #         if(!tmp)
> #         {
> #            synchronized
> #            {
> #                tmp = s;
> #                if(!tmp)
> #                {
> #                   volatile tmp = new Singleton();
> #                   s = tmp;
> #                }
> #            }
> #         }
> #         return s;
> #     }
> # }
>
> With the above, the block volatile might be useful if we wanted to do
extra
> initialization of the singleton before assigning to s, thus replacing:
>
> # volatile tmp = new Singleton();
>
> with:
>
> # volatile {
> #    tmp = new Singleton();
> #    // do stuff
> # }
>
>
> Sean
>
>


August 20, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:cg5e3f$iep$1@digitaldaemon.com...
> In article <cg412i$2tt9$1@digitaldaemon.com>, Matthew says...
> >
> >And if that's the case, then what about allowing the Python like syntax
> >
> >    int l = length(x); // Equivalent to int l = x.length;
> >
> >I'm not proposing this last bit, mind, just interested in hearing opinions on the matter.
>
> D already supports this in reverse for arrays.  ie. length(T[] x) can be called as: length(x) or x.length.  Since this is the case, and assuming it hasn't already been done, it would be nice to expose the default parameters as D functions.  So we could call sizeof(x), length(x), etc.  By the same token, it would be nice to have this be consistent for all primitive types rather than just for array types.

Certainly, one the main points is to keep handling of all types consistent.

And, yes, I like the application the principle of sizeof() also.


August 20, 2004
Sean Kelly schrieb in <cg5e3f$iep$1@digitaldaemon.com>:
> D already supports this in reverse for arrays.  ie. length(T[] x) can be
> called as: length(x) or x.length.  Since this is the case, and assuming it
> hasn't already been done, it would be nice to expose the default
> parameters as D functions.  So we could call sizeof(x), length(x), etc.
> By the same token, it would be nice to have this be consistent for all
> primitive types rather than just for array types.

I strongly opose this. This will break lots of existing length() etc.
functions.

If ever enable this only when a special pragma switch is included in the sources.

Thomas



August 20, 2004
In article <cg61nf$u96$1@digitaldaemon.com>, antiAlias says...
>
>You'll forgive me Sean, but the double-locking 'style' was driven out of Java developers after it was shown to be mostly futile (I think it may have been Doug Lea who demonstrated that).

That's fine :)  I mostly used it as an example beceause I had the Andrei and Scott's DDJ articles on it in front of me at the time.

>The recommended approach over there is to construct singletons statically

Yup.  And this would work in D just as well.  Since apps all begin with only one thread, eager construction seems to make far more sense than the lazy method.

>Which leads to a question: how does the compiler deal with circular dependencies across static-constructors? Let's try it out ...
>
>class A
>{
>        static B b;
>
>        static this()
>        {
>                printf ("A\n");
>                b = new B;
>        }
>}
>
>class B
>{
>        static A a;
>
>        static this()
>        {
>                printf ("B\n");
>                a = new A;
>        }
>}
>
>Note that I wouldn't recommend this as a practice to anyone, but it may
>occur accidentally where multiple modules are involved (I've done that with
>Mango). No compile errors ~ emits:
>A
>B
>
>In fact, the only obvious means to get the output in a different order is to
>switch the class order within the file; that is, placing B above A yields:
>B
>A
>
>Is there no dependency checking done for static constructors? Is this a bug? Am I being particularly dense today?

I was wondering about this.  What if A and B were in separate modules?


Sean