www.digitalmars.com         C & C++   DMDScript  

D - volatile

reply "Matthew Wilson" <matthew stlsoft.org> writes:
Walter

I've recently spent a fair amount of time on the c.l.c.m ng, learning about
volatile, and atomicity.

I think D should, as part of the *language*, provide an atomic integer type
(or allow the use of the volatile keyword to apply to integers within an
appropriate size range) that guarantees atomicity, using whatever constructs
are necessary to the architecture. This would be a massive advantage over
C++ (and I know you're looking for them).

I'm more than happy if it's not via volatile, which has a meaning of its
own.

I think either we have a qualifier - I suggest "atomic" - or we have a set
of atomic types, which I imagine would be anything up to and including int.
(It'd be nice if we could have long as well.)

I would prefer the qualifier.

Note that I'm not really talking about synchronised, since that uses
crit-sects (or non-Win32 equiv), but rather atomic operations.

Matthew
Sep 04 2003
next sibling parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
Wouldn't the set of operations be very limited, and platform dependent?
You're talking about ops like test-and-set, or atomic inc or store, right?

On Intel, I don't think even ints are atomic unless properly aligned or if
you use the LOCK prefix.  I don't think most platforms have a LOCK prefix
though.

Sean

"Matthew Wilson" <matthew stlsoft.org> wrote in message
news:bj7em5$e37$3 digitaldaemon.com...
 Walter

 I've recently spent a fair amount of time on the c.l.c.m ng, learning
about
 volatile, and atomicity.

 I think D should, as part of the *language*, provide an atomic integer
type
 (or allow the use of the volatile keyword to apply to integers within an
 appropriate size range) that guarantees atomicity, using whatever
constructs
 are necessary to the architecture. This would be a massive advantage over
 C++ (and I know you're looking for them).

 I'm more than happy if it's not via volatile, which has a meaning of its
 own.

 I think either we have a qualifier - I suggest "atomic" - or we have a set
 of atomic types, which I imagine would be anything up to and including
int.
 (It'd be nice if we could have long as well.)

 I would prefer the qualifier.

 Note that I'm not really talking about synchronised, since that uses
 crit-sects (or non-Win32 equiv), but rather atomic operations.

 Matthew
Sep 04 2003
next sibling parent reply "Matthew Wilson" <matthew stlsoft.org> writes:
 Wouldn't the set of operations be very limited, and platform dependent?
Yes, the idea is that D would handle that for us
 You're talking about ops like test-and-set, or atomic inc or store, right?
Yes
 On Intel, I don't think even ints are atomic unless properly aligned or if
 you use the LOCK prefix.  I don't think most platforms have a LOCK prefix
 though.
That is my understanding in both regards. The use of atomic would, of course, have differing costs, and its use would require a non-cavalier approach. But then D has ptrs, which is the same mentality.
Sep 04 2003
parent reply Mike Wynn <mike l8night.co.uk> writes:
Matthew Wilson wrote:
 
On Intel, I don't think even ints are atomic unless properly aligned or if
you use the LOCK prefix.  I don't think most platforms have a LOCK prefix
though.
That is my understanding in both regards. The use of atomic would, of course, have differing costs, and its use would require a non-cavalier approach. But then D has ptrs, which is the same mentality.
I'm not sure how ptrs (I assume you mean pointers) are related to atomic ops. MIPS and PowerPC (and I assume other RISC) have load linked/store conditional type operations, where the store will not complete if the "linked" flag is clear (cleared by task switch/interrupt etc) [note some WinCE MIPS devices have a reduced MIPS instruction set that does NOT have the atomic ops] ARM has locked exchange. on uniprocessor systems in general all read or writes will be atomic interrupts cause the pipeline to be flushed etc so your data will be consistent. the awkward instruction is atomic compare and exchange if it's not supported in hardware. on multi processor systems the CPU's tend to support some form of lock, usually a locked exchange, read and writes need replacing with exchanges although a read / write may be atomic you may need to notify the cache to write-through. again compare exchange required a mutex or similar. I do think D should support some form of atomic ops just a compare exchange would be all that is needed bit Atomic::cmp_exchange( int o, inout int v, int * dest ) {// atomic form of if ( *dest == o ) { *dest = v; return true; } v = *dest; return false; } Atomic.cmp_exchange( i, i, dest ); // can be used as atomic read or write.
Sep 05 2003
next sibling parent "Matthew Wilson" <matthew stlsoft.org> writes:
"Mike Wynn" <mike l8night.co.uk> wrote in message
news:bjal6a$205u$1 digitaldaemon.com...
 Matthew Wilson wrote:
On Intel, I don't think even ints are atomic unless properly aligned or
if
you use the LOCK prefix.  I don't think most platforms have a LOCK
prefix
though.
That is my understanding in both regards. The use of atomic would, of course, have differing costs, and its use would require a non-cavalier approach. But then D has ptrs, which is the same mentality.
I'm not sure how ptrs (I assume you mean pointers) are related to atomic ops.
I just meant that ptrs are part of the C ethos "power in the hands of the programmer", as atomic would also be
Sep 05 2003
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Mike Wynn" <mike l8night.co.uk> wrote in message
news:bjal6a$205u$1 digitaldaemon.com...
 I do think D should support some form of atomic ops
 just a compare exchange would be all that is needed

 bit Atomic::cmp_exchange( int o, inout int v, int * dest )
 {// atomic form of
 if ( *dest == o ) { *dest = v; return true; }
 v = *dest;
 return false;
 }


 Atomic.cmp_exchange( i, i, dest ); // can be used as atomic read or write.
Why not just do that as a library function? That's what I've done before, writing it in inline assembler.
Sep 11 2003
parent reply "Matthew Wilson" <matthew stlsoft.org> writes:
 Atomic.cmp_exchange( i, i, dest ); // can be used as atomic read or
write.
 Why not just do that as a library function? That's what I've done before,
 writing it in inline assembler.
Hmm. It's a puzzle, this one. By nature I am firmly in the Stroustrup camp, i.e. I prefer libraries to language features. The same instinct informs on what I hope to see in the breakdown between D itself, the D runtime library and external libraries. However, in this case I am strongly of the contrary opinion. To be honest, I don't know that I can form a cogent argument at this time. I may have to get back to you on that. I will say that I've been spending a lot of time thinking about atomicity in the languages, and C/C++'s pretty useless volatile keyword. I *strongly* want this to be provided more inately by the language in D.
Sep 11 2003
parent Mike Wynn <mike l8night.co.uk> writes:
Matthew Wilson wrote:
Atomic.cmp_exchange( i, i, dest ); // can be used as atomic read or write.
Why not just do that as a library function? That's what I've done before,
writing it in inline assembler.
Hmm. It's a puzzle, this one. By nature I am firmly in the Stroustrup camp, i.e. I prefer libraries to language features. The same instinct informs on what I hope to see in the breakdown between D itself, the D runtime library and external libraries. However, in this case I am strongly of the contrary opinion. To be honest, I don't know that I can form a cogent argument at this time. I may have to get back to you on that. I will say that I've been spending a lot of time thinking about atomicity in the languages, and C/C++'s pretty useless volatile keyword. I *strongly* want this to be provided more inately by the language in D.
my belief that atomic op's should be in the language and not within a library is their use. the main time I've used atomic ops was on append only lists where speed was important to avoid the need for a mutex (or similar). I don't mind if the syntax makes it look like a library call (so it can be implemented as a library on an arch that does not have the primatives) but it should be reduced in the object code to the smallest/fastest possible code that the platform allows. if implemented within the compiler then on x86 "lock smashing" can be performed by the D runtime lib etc. i.e. atomic read/write would generate `lea edx, <some-address>; xchg eax, [edx];` however if it is running on a uni processor the implicit `lock` causes a cache flush etc, but is not actually required so can be replaced with `mov eax, <some-address>; nop` or `mov <some-address>, eax; nop` before the code is run.
Sep 11 2003
prev sibling parent "Fabian Giesen" <rygNO SPAMgmx.net> writes:
 Wouldn't the set of operations be very limited, and platform
 dependent? You're talking about ops like test-and-set, or atomic inc
 or store, right?

 On Intel, I don't think even ints are atomic unless properly aligned
 or if you use the LOCK prefix.  I don't think most platforms have a
 LOCK prefix though.
Any SMP-capable platform supports atomic compare-exchange (or equivalent) instructions, simply because such an instruction is *required* to make atomicity work - after all, the OS needs some way of reliable implementing constructs such as mutexes or semaphores. -fg
Sep 08 2003
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
I think the synchronized block would fit the bill - remember that class
operations can be synchronized as well. Optimizing it to using a LOCK prefix
might be possible.

"Matthew Wilson" <matthew stlsoft.org> wrote in message
news:bj7em5$e37$3 digitaldaemon.com...
 Walter

 I've recently spent a fair amount of time on the c.l.c.m ng, learning
about
 volatile, and atomicity.

 I think D should, as part of the *language*, provide an atomic integer
type
 (or allow the use of the volatile keyword to apply to integers within an
 appropriate size range) that guarantees atomicity, using whatever
constructs
 are necessary to the architecture. This would be a massive advantage over
 C++ (and I know you're looking for them).

 I'm more than happy if it's not via volatile, which has a meaning of its
 own.

 I think either we have a qualifier - I suggest "atomic" - or we have a set
 of atomic types, which I imagine would be anything up to and including
int.
 (It'd be nice if we could have long as well.)

 I would prefer the qualifier.

 Note that I'm not really talking about synchronised, since that uses
 crit-sects (or non-Win32 equiv), but rather atomic operations.

 Matthew
Sep 04 2003
next sibling parent "Matthew Wilson" <matthew stlsoft.org> writes:
I see them as different things, but am shooting from the hip here. Let me
have a ponder, and I'll put forward a more cogent argument

"Walter" <walter digitalmars.com> wrote in message
news:bj89ai$1l9g$2 digitaldaemon.com...
 I think the synchronized block would fit the bill - remember that class
 operations can be synchronized as well. Optimizing it to using a LOCK
prefix
 might be possible.

 "Matthew Wilson" <matthew stlsoft.org> wrote in message
 news:bj7em5$e37$3 digitaldaemon.com...
 Walter

 I've recently spent a fair amount of time on the c.l.c.m ng, learning
about
 volatile, and atomicity.

 I think D should, as part of the *language*, provide an atomic integer
type
 (or allow the use of the volatile keyword to apply to integers within an
 appropriate size range) that guarantees atomicity, using whatever
constructs
 are necessary to the architecture. This would be a massive advantage
over
 C++ (and I know you're looking for them).

 I'm more than happy if it's not via volatile, which has a meaning of its
 own.

 I think either we have a qualifier - I suggest "atomic" - or we have a
set
 of atomic types, which I imagine would be anything up to and including
int.
 (It'd be nice if we could have long as well.)

 I would prefer the qualifier.

 Note that I'm not really talking about synchronised, since that uses
 crit-sects (or non-Win32 equiv), but rather atomic operations.

 Matthew
Sep 04 2003
prev sibling parent "Jeroen van Bemmel" <someone somewhere.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:bj89ai$1l9g$2 digitaldaemon.com...
 I think the synchronized block would fit the bill - remember that class
 operations can be synchronized as well. Optimizing it to using a LOCK
prefix
 might be possible.
I thought a synchronized block implicitly uses a semaphore? that is too coarse grained and inefficient in cases where atomic operations can be used instead, they are much more efficient and non-blocking. Since atomic operations are only supported for primitive types (typically <= 64 bits), they warrant a separate type or 'atomic' keyword (but then that would somehow need to be restricted to only be used in combination with primitive types) Solving it by relying on a compiler optimization such as the following: class X { int i; synchronized m() { i++; <-- reasoning: 'synchronized' && primitive_type && only operation => do atomic operation } } would IMO be too implicit and thus dangerous: - compiling with optimizations off could yield incorrect results (if not carefully implemented by the compiler) - method suddenly no longer blocking, although 'synchronized' usually is - adding a statement after 'i++' will change the generated code completely I vote for a separate 'atomic' type (typical size 32 bits) with operations 'set', 'test_and_set', 'compare_and_exchange', etc. It need not be built into the compiler though, the runtime library can support it using inline assembly + version sections for each supported architecture
Sep 06 2003