Topic: Proposal: atomic


Author: 520001085531-0001@t-online.de ("Uenal Mutlu")
Date: Mon, 25 Apr 2005 15:17:36 GMT
Raw View
"Alberto Barbati" wrote
> Uenal Mutlu wrote:
> >
> > It is not recommended to use "atomic_t" for this since this
> > is already used differently at many places.
>
> I don't understand this sentence. Could you please elaborate? In which
> other places sig_atomic_t is already used differently? How would this
> "different use" impair the ability of sig_atomic_t to provide the effect
> you seek?  (BTW, it's sig_atomic_t, not atomic_t).

I meant "atomic_t". Just do a googling.

> > On the other hand the proposed "atomic" is not a type but
> > only a type qualifier like volatile and const.
>
> Why would that be desirable? Would a generic implementation really be
> able to provide atomic semantic for anything different than ints? I
> don't think so. Having atomic a qualifier that would only apply to a
> subset of types (such subset would probably *not* include UDTs) does not
> make much sense to me.

Because the CPU must provide the support for it. Most modern
CPUs have atomic instructions only for their natural word size (ie. int).
But this is not a problem since everything else can be implemented
by using just this primitive as a helper.




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Uenal Mutlu" <520001085531-0001@t-online.de>
Date: Wed, 20 Apr 2005 03:28:00 +0200
Raw View
Atomic operations are very important for synchronization,
shared access to resources, and for resource locking
in multitasking/multithreading applications. They are also
essential in implementing so called lock-free data structures
and algorithms.

All modern CPUs have such instructions for integers,
or at least for "int".

Since multitasking/multithreading has become very
important nowadays the next C++ standard should have
the "atomic" qualifier for integers (and optionally also for
pointers).

Example usage:

    atomic int foo;
    atomic int bar = 5;
    bar++;
    foo = bar - 2;

It should implicitly define the variable as volatile (since for
atomic operations variables must be seen as volatile to
prevent them from being optimized out by the compiler).

Obviously all r/w operations on such variables must be done
atomically. This can simply be implemented by just linking to
some CPU specific functions in a library (for example the
InterlockedXXX functions of Win32), or by inline _asm.

The major point besides having atomic operations is also to see
easily from the source code that the variable has this property.

It is not recommended to use "atomic_t" for this since this
is already used differently at many places.
On the other hand the proposed "atomic" is not a type but
only a type qualifier like volatile and const.


--
U.Mutlu & TFYI






Author: solodon@tamu.put_edu_here (Yuriy Solodkyy)
Date: Wed, 20 Apr 2005 05:45:59 GMT
Raw View
Why should it be in the language? You can always define something like:

template <class T>
class atomic
{
.
 T operator++()
 {
  SomeSortOfAutoLock guard(SomeLock);
  return m_t++;
 }

 volatile T m_t;
};

template <>
class atomic<int>
{
.
 int operator++() { InterlockedIncrement(&m_t); }
 volatile int m_t;
}

Yuriy

Uenal Mutlu wrote:
> Atomic operations are very important for synchronization,
> shared access to resources, and for resource locking
> in multitasking/multithreading applications. They are also
> essential in implementing so called lock-free data structures
> and algorithms.
>
> All modern CPUs have such instructions for integers,
> or at least for "int".
>
> Since multitasking/multithreading has become very
> important nowadays the next C++ standard should have
> the "atomic" qualifier for integers (and optionally also for
> pointers).
>
> Example usage:
>
>     atomic int foo;
>     atomic int bar = 5;
>     bar++;
>     foo = bar - 2;
>
> It should implicitly define the variable as volatile (since for
> atomic operations variables must be seen as volatile to
> prevent them from being optimized out by the compiler).
>
> Obviously all r/w operations on such variables must be done
> atomically. This can simply be implemented by just linking to
> some CPU specific functions in a library (for example the
> InterlockedXXX functions of Win32), or by inline _asm.
>
> The major point besides having atomic operations is also to see
> easily from the source code that the variable has this property.
>
> It is not recommended to use "atomic_t" for this since this
> is already used differently at many places.
> On the other hand the proposed "atomic" is not a type but
> only a type qualifier like volatile and const.
>
>
> --
> U.Mutlu & TFYI
>
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Uenal Mutlu" <520001085531-0001@t-online.de>
Date: Wed, 20 Apr 2005 09:30:53 +0200
Raw View
"Yuriy Solodkyy" wrote
> Why should it be in the language? You can always define something like:
>
> template <class T>
> class atomic
> {
> .
> T operator++()
> {
> SomeSortOfAutoLock guard(SomeLock);
> return m_t++;
> }

"Some lock" is nice said... :-)
You would, guess, need atomic for implementing such a lock... :-)
But this op is usually done differently than what you have written above.

> volatile T m_t;
> };
>
> template <>
> class atomic<int>
> {
> .
> int operator++() { InterlockedIncrement(&m_t); }
> volatile int m_t;
> }
>
> Yuriy

You cannot define all types atomic. Only integers classify.
There is also a data alignment issue. Such variables must be
properly aligned.
Thanks, but a little bit too naive I would say.
Atomic is really a very important issue. It should be standardized.


> Uenal Mutlu wrote:
> > Atomic operations are very important for synchronization,
> > shared access to resources, and for resource locking
> > in multitasking/multithreading applications. They are also
> > essential in implementing so called lock-free data structures
> > and algorithms.
> >
> > All modern CPUs have such instructions for integers,
> > or at least for "int".
> >
> > Since multitasking/multithreading has become very
> > important nowadays the next C++ standard should have
> > the "atomic" qualifier for integers (and optionally also for
> > pointers).
> >
> > Example usage:
> >
> >     atomic int foo;
> >     atomic int bar = 5;
> >     bar++;
> >     foo = bar - 2;
> >
> > It should implicitly define the variable as volatile (since for
> > atomic operations variables must be seen as volatile to
> > prevent them from being optimized out by the compiler).
> >
> > Obviously all r/w operations on such variables must be done
> > atomically. This can simply be implemented by just linking to
> > some CPU specific functions in a library (for example the
> > InterlockedXXX functions of Win32), or by inline _asm.
> >
> > The major point besides having atomic operations is also to see
> > easily from the source code that the variable has this property.
> >
> > It is not recommended to use "atomic_t" for this since this
> > is already used differently at many places.
> > On the other hand the proposed "atomic" is not a type but
> > only a type qualifier like volatile and const.
> >
> >
> > --
> > U.Mutlu & TFYI







Author: stkim@yujinrobot.com ("Kim, Seungtai")
Date: Wed, 20 Apr 2005 22:45:27 GMT
Raw View
"Yuriy Solodkyy"
> Why should it be in the language? You can always define something like:
>
> template <class T>
> class atomic
> {
> .
> T operator++()
> {
> SomeSortOfAutoLock guard(SomeLock);
> return m_t++;
> }
>
> volatile T m_t;
> };
>
> template <>
> class atomic<int>
> {
> .
> int operator++() { InterlockedIncrement(&m_t); }
> volatile int m_t;
> }
>
> Yuriy

It's not atomic. Any of the function call can be interrupted even you code
it as a inline function. And also the volatile specifier can not guarantee
the atomic operation.

I think that the atomic operation issus is not on a programming language,
but it's on a operating system. How could we define that it prevent an interrupt
by another program(made by another language)? How could we define that
it prevent the interrupt signal even we don't know about the multi-thread and
multi-process. They are not defined on a programming language. They are all
the Operating System issue.

--
S Kim <stkim@yujinrobot.com>


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Fri, 22 Apr 2005 19:43:31 GMT
Raw View
Uenal Mutlu wrote:
>
> It is not recommended to use "atomic_t" for this since this
> is already used differently at many places.

I don't understand this sentence. Could you please elaborate? In which
other places sig_atomic_t is already used differently? How would this
"different use" impair the ability of sig_atomic_t to provide the effect
you seek?  (BTW, it's sig_atomic_t, not atomic_t).

> On the other hand the proposed "atomic" is not a type but
> only a type qualifier like volatile and const.

Why would that be desirable? Would a generic implementation really be
able to provide atomic semantic for anything different than ints? I
don't think so. Having atomic a qualifier that would only apply to a
subset of types (such subset would probably *not* include UDTs) does not
make much sense to me.

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: solodon@tamu.put_edu_here (Yuriy Solodkyy)
Date: Fri, 22 Apr 2005 19:43:50 GMT
Raw View
Well, I believe you can generalize the idea of atomicity for other types
too and implement it via synchronization primitives available in your
OS. Boost has some portable ones if that is of concern. Also the idea
here was not to discuss how to implement general case but rather that
you can always specialize it for int and implement efficiently via OS
primitives (e.g. InterlockedIncrement,InterlockedExchange etc.). If
standard alignment requirements of int are not sufficient for those
primitives, you can always union it with a type that has desired
alignment requirements. All that I'm trying to argue here is that there
is no need to change the language to add this functionality and that C++
provides enough powerful means to implement it efficiently.

Maybe I don't understand all the issues involved in atomicity, but will
appreciate then if you explain in greater details your concerns.

Yuriy

Uenal Mutlu wrote:
> "Yuriy Solodkyy" wrote
>
>>Why should it be in the language? You can always define something like:
>>
>>template <class T>
>>class atomic
>>{
>>.
>>T operator++()
>>{
>>SomeSortOfAutoLock guard(SomeLock);
>>return m_t++;
>>}
>
>
> "Some lock" is nice said... :-)
> You would, guess, need atomic for implementing such a lock... :-)
> But this op is usually done differently than what you have written above.
>
>
>>volatile T m_t;
>>};
>>
>>template <>
>>class atomic<int>
>>{
>>.
>>int operator++() { InterlockedIncrement(&m_t); }
>>volatile int m_t;
>>}
>>
>>Yuriy
>
>
> You cannot define all types atomic. Only integers classify.
> There is also a data alignment issue. Such variables must be
> properly aligned.
> Thanks, but a little bit too naive I would say.
> Atomic is really a very important issue. It should be standardized.
>
>
>
>>Uenal Mutlu wrote:
>>
>>>Atomic operations are very important for synchronization,
>>>shared access to resources, and for resource locking
>>>in multitasking/multithreading applications. They are also
>>>essential in implementing so called lock-free data structures
>>>and algorithms.
>>>
>>>All modern CPUs have such instructions for integers,
>>>or at least for "int".
>>>
>>>Since multitasking/multithreading has become very
>>>important nowadays the next C++ standard should have
>>>the "atomic" qualifier for integers (and optionally also for
>>>pointers).
>>>
>>>Example usage:
>>>
>>>    atomic int foo;
>>>    atomic int bar = 5;
>>>    bar++;
>>>    foo = bar - 2;
>>>
>>>It should implicitly define the variable as volatile (since for
>>>atomic operations variables must be seen as volatile to
>>>prevent them from being optimized out by the compiler).
>>>
>>>Obviously all r/w operations on such variables must be done
>>>atomically. This can simply be implemented by just linking to
>>>some CPU specific functions in a library (for example the
>>>InterlockedXXX functions of Win32), or by inline _asm.
>>>
>>>The major point besides having atomic operations is also to see
>>>easily from the source code that the variable has this property.
>>>
>>>It is not recommended to use "atomic_t" for this since this
>>>is already used differently at many places.
>>>On the other hand the proposed "atomic" is not a type but
>>>only a type qualifier like volatile and const.
>>>
>>>
>>>--
>>>U.Mutlu & TFYI
>
>
>
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Fri, 22 Apr 2005 19:45:52 GMT
Raw View
Uenal Mutlu wrote:
> Atomic operations are very important for synchronization,
> shared access to resources, and for resource locking
> in multitasking/multithreading applications. They are also
> essential in implementing so called lock-free data structures
> and algorithms.

Yes, but they are not sufficient.  There's also a requirement for
memory barriers (usually combined with the atomic operations).

> All modern CPUs have such instructions for integers,
> or at least for "int".
>
> Since multitasking/multithreading has become very
> important nowadays the next C++ standard should have
> the "atomic" qualifier for integers (and optionally also for
> pointers).
>
> Example usage:
>
>     atomic int foo;
>     atomic int bar = 5;
>     bar++;
>     foo = bar - 2;
>
> It should implicitly define the variable as volatile (since for
> atomic operations variables must be seen as volatile to
> prevent them from being optimized out by the compiler).
>
> Obviously all r/w operations on such variables must be done
> atomically. This can simply be implemented by just linking to
> some CPU specific functions in a library (for example the
> InterlockedXXX functions of Win32), or by inline _asm.

That's all very well for single reads and writes, but most lockless
algorithms require some kind of atomic read-modify-write operations.
In the code above, should "bar++" be evaluated atomically?  How about
"foo = bar - 2"?  While some C++ operators map reasonably well to
atomic operations on some architectures, in general they do not; and
some of the atomic operations that are commonly available don't map at
all well to C++ operators!  Then there's the need to specify memory
barriers associated with operations.  I think many atomic operations
should be written as function calls.

> The major point besides having atomic operations is also to see
> easily from the source code that the variable has this property.
>
> It is not recommended to use "atomic_t" for this since this
> is already used differently at many places.
> On the other hand the proposed "atomic" is not a type but
> only a type qualifier like volatile and const.

But it is operations that are atomic, not variables.  One might
want to use atomic operations at some point in the program where
a variable is shared and ordinary operations at other points
where it isn't.

Having said that, depending on the architecture, atomic operations
may require larger alignment for the operand than is normal for its
type, or may require extra space for a spinlock, so special types
might be necessary.

Finally, atomic operations can only be specified within a memory model
that acknowledges multiple threads, which the current C++ memory model
does not.  I'm somewhat involved with a group that is currently
working on this, with the encouragement and involvement of the
standard committee.

So far the group has produced two papers: "Memory Model for
multithreaded C++"
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1680.pdf>
and "Memory model for multithreaded C++: Issues"
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1777.pdf>.
You can find archives of group discussions here:
<http://decadentplace.org.uk/pipermail/cpp-threads_decadentplace.org.uk/>.

--
Ben Hutchings
Larkinson's Law: All laws are basically false.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Fri, 22 Apr 2005 19:45:57 GMT
Raw View
"Kim, Seungtai" wrote:
> "Yuriy Solodkyy"
>> Why should it be in the language? You can always define something like:
>>
>> template <class T>
>> class atomic
>> {
>> .
>> T operator++()
>> {
>> SomeSortOfAutoLock guard(SomeLock);
>> return m_t++;
>> }
>>
>> volatile T m_t;
>> };
>>
>> template <>
>> class atomic<int>
>> {
>> .
>> int operator++() { InterlockedIncrement(&m_t); }
>> volatile int m_t;
>> }
>>
>> Yuriy
>
> It's not atomic. Any of the function call can be interrupted even you code
> it as a inline function.

In the primary template, yes, but locking should prevent another
thread from interrupting operations on that particular object.
However this does make the type fairly useless for its intended
use in *lockless* algorithms!

The Win32 function InterlockedIncrement is absolutely atomic.

> And also the volatile specifier can not guarantee the atomic
> operation.

Right, though it does prevent certain compiler optimisations that may
be undesirable.  The exact semantics are unfortunately implementation-
dependent at present.

> I think that the atomic operation issus is not on a programming
> language, but it's on a operating system. How could we define that
> it prevent an interrupt by another program(made by another
> language)?

It doesn't matter; the other program isn't using this object.

> How could we define that it prevent the interrupt signal
> even we don't know about the multi-thread and multi-process. They
> are not defined on a programming language. They are all the
> Operating System issue.

Actually multithreading does impact on the language specification; see
<http://groups.google.co.uk/groups?selm=2oj30bFahektU1%40uni-berlin.de>.

--
Ben Hutchings
Larkinson's Law: All laws are basically false.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: 520001085531-0001@t-online.de ("Uenal Mutlu")
Date: Mon, 25 Apr 2005 01:24:17 GMT
Raw View
"Yuriy Solodkyy" <solodon@tamu.put_edu_here> wrote
> Well, I believe you can generalize the idea of atomicity for other types
> too and implement it via synchronization primitives available in your
> OS. Boost has some portable ones if that is of concern. Also the idea
> here was not to discuss how to implement general case but rather that
> you can always specialize it for int and implement efficiently via OS
> primitives (e.g. InterlockedIncrement,InterlockedExchange etc.). If
> standard alignment requirements of int are not sufficient for those
> primitives, you can always union it with a type that has desired
> alignment requirements. All that I'm trying to argue here is that there
> is no need to change the language to add this functionality and that C++
> provides enough powerful means to implement it efficiently.
>
> Maybe I don't understand all the issues involved in atomicity, but will
> appreciate then if you explain in greater details your concerns.

Actually what is needed is just one or two data types which guarantee
atomic operations: integer and pointer. They would serve as atomic primitives.
This opens up the way for everything else. For example with these
atomic primitives you can solve also all locking problems for any
other type by writing a generic locking class. Everywhere where
resource locking is required one just does it with the locking class
which internally uses an atomic integer. By combining this with
the system wide unique current thread id a general purpose fast
locking method is possible even with a recursive locking feature
(ie. where a thread won't deadlock itself by locking the resource
twice or more).
And: resource locking should not mean to lock the whole object.
The user should have the freedom in which methods and in
which scope a resource should be locked.

This is of course just one, but IMO very important, example where
atomic is useful. There is also the issue of porting multithreading
applications to other platforms and compilers. Or imagine simple
exchange of code snippets for discussion, review, publishing.
>From the "atomic" keyword everybody would know what is meant.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]