Portable Compare And Swap (atomic operations) C/C++ library?
Asked Answered
I

9

31

Is there any small library, that wrapps various processors' CAS-like operations into macros or functions, that are portable across multiple compilers?

PS. The atomic.hpp library is inside boost::interprocess::detail namespace. The author refuses to make it a public, well maintained library.

Lets reopen the question, and see if there are any other options?

Irita answered 21/7, 2009 at 10:25 Comment(4)
...insert the usual complaint about c and c++ not being the same thing... Steve Gilham's nice answer is good in c++ and simply won't work for c as boost is a c++ library.Blabber
Yes, but what I want is a C++ library, I've written "C/C++" because someone could avoid answering about C library, which is also fine for me.Irita
I'm confused about the insinuation that Boost is not "a public, well-maintained library." Can you elaborate?Interlineate
For anyone who finds this question in a search engine today, the atomic_compare_exchange_* family of functions is now in both <stdatomic.h> in the C standard library and <atomic> in the C++ standard library.Magnum
P
15

Intel Threading Building Blocks has a nice portable atomic<T> template which does what you want. But whether it is a small library or not can of course be debated..

Pseudoscope answered 28/7, 2009 at 13:15 Comment(1)
I adopted the TBB into my project. Thanks.Irita
N
30

OPA (Open Portable Atomics) could be a good fit for your needs. https://trac.mcs.anl.gov/projects/openpa/

It provides a consistent C API to common atomic operations across multiple platforms under an MIT-style license. The library is small and certainly meets your size requirements. The current platform list is:

  • GCC inline assembly for x86, x86_64, ia64, PPC 440, and MIPS 5K processors. Several compilers with GCC-compatible-ish front-ends are also supported on the same architectures, such as icc, PGI, and IBM's xlc.
  • GCC atomic intrinsics, so most GCC-4.1+ installations are supported.
  • The SUN Solaris atomic operations library.
  • Windows NT intrinsics (although you currently have to do a little bit of extra work to build on Windows).
  • Two pseudo-platforms, pthread mutex based emulation for portability to otherwise unsupported platforms (while sacrificing some performance), and an "unsafe" implementation for use in code that is conditionally compiled to be single-threaded code.

I've never used it in a C++ program, although it ought to work with little or no changes. I'd be happy to tweak it if you run into trouble (just mail [email protected]).

Neisse answered 20/8, 2009 at 14:16 Comment(1)
I stumbled upon your answer and it's exactly what I needed, Thanks!Scrivings
J
25

The boost interprocess library might be what you are after -- the Atomic.hpp include file contains compare-and-swap implementations for a variety of platforms and compilers.

Jacoby answered 21/7, 2009 at 10:39 Comment(3)
Thank you, it's exactly what I asked.Irita
But Boost's atomic.hpp only has atomics for 32-bit ints. A good atomic library would also have 64-bit int atomics and pointer atomics.Ike
Of course nowadays, the C++11 atomic types should be chosen in preference to these, if you have the opportunity to use a recent enough compiler version.Jacoby
P
15

Intel Threading Building Blocks has a nice portable atomic<T> template which does what you want. But whether it is a small library or not can of course be debated..

Pseudoscope answered 28/7, 2009 at 13:15 Comment(1)
I adopted the TBB into my project. Thanks.Irita
J
11

You might be interested in Glib's Atomic Operations functions,

g_atomic_int_compare_and_exchange()

implements the CAS semantics for various architectures. The implementation itself is relatively easy to understand and can be used stand-alone without too much effort, you can find it at svn.gnome.org/viewvc/ under glib/trunk/glib/gatomic.{c,h}. Hope this helps!

Janis answered 24/7, 2009 at 22:34 Comment(0)
T
9

On Mac OS X and Windows there are builtin CompareAndSwap functions you should be using anyway (InterlockedCompareExchange() and OSAtomicCompareAndSwapPtrBarrier() respectively). Thus will work regardless of the compilers on those platforms.

On other Unixes it is a bit trickier, if you are using GCC 4.1 or later you can just use its builtin __sync_val_compare_and_swap(), and many though not all unix compilers support reasonable gcc extensions since a lot of code originating on Linux assumes they are present.

So if you want to wrap them up in a way that works with most all compilers for all processors on OS X and Windows, and with GCC and some other compilers on other platforms you should do something like:

boolean CompareAndSwapPointer(volatile * void * ptr,
                                  void * new_value,
                                  void * old_value) {
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
  return OSAtomicCompareAndSwapPtr (old_value, new_value, ptr);
#elif defined(_MSC_VER)
  return InterlockedCompareExchange(ptr, new_value, old_value);
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
  return __sync_val_compare_and_swap(ptr, old_value, new_value);
#else
#  error No implementation
#endif
}

That is not tested, but I think it should be correct. Note how all the OS libraries take the args in different orders ;-)

Obviously you can do a few version for the different size compare and swaps and wrap them in templates if you want. The APIs are mostly C based and encode the type information into the functions in such a way that it is sort of nasty for people used to parameterizing types via templates.

Thrombo answered 27/7, 2009 at 17:54 Comment(3)
InterlockedCompareExchange() doesn't return a bool: msdn.microsoft.com/en-us/library/ms683560%28VS.85%29.aspxLeda
Similarly the incorrect GCC intrinsic is used, try this one: __sync_bool_compare_and_swapGeelong
I personally used the MSDN Intrinsic and did an if then else condition on the resulting value, based on that either returned false or true. Is there another way of doing it ?Skulduggery
F
6

There is the library of the atomic_ops project by Boehm. Dunno about the license, though.

Floristic answered 28/7, 2009 at 20:52 Comment(1)
"Our intent is to make it easy to use libatomic_ops, in both free and proprietary software. Hence most code that we expect to be linked into a client application is covered by an MIT-style license. A few library routines are covered by the GNU General Public License. These are put into a separate library, libatomic_ops_gpl.a."Cauldron
C
3

There is a proposed C++0x-compatible Boost atomics library: http://www.chaoticmind.net/~hcb/projects/boost.atomic/

The purpose of this library is to provide an implementation of atomic operations for boost, based on the interface specified by the C++0x draft standard. It aims to make transitioning to std::atomic easy, as well as providing a means to make code using this C++0x feature compilable on older systems.

It's obviously not part of Boost yet, but you can check out the review thread here: http://lists.boost.org/Archives/boost/2009/12/160195.php

Boost.Atomic is now in a form that I consider calling it a release. It has support for "true" atomic variables on:

  • gcc/x86, 32-bit (tested on Linux, FreeBSD)
  • gcc/x86, 64-bit (tested on Linux)
  • gcc/powerpc32 (tested on Linux, Mac OS X)
  • gcc/powerpc64 (untested)
  • generic Win32 (tested with Visual Studio Express on Win XP)

For all others it falls back gracefully to locked operation. There is proper quickbook documentation, including a hopefully illustrative example section.

Cauldron answered 16/8, 2010 at 19:19 Comment(1)
I seems to have been accepted into Boost in Nov. 2011: lists.boost.org/boost-announce/2011/11/0337.phpRandee
C
2

What the author said (in the link you provided) was "I think you can use them safely until some official Boost library comes". Deferring the interface change until "when atomic functions are going to be present in C++0x".

Whatever you use today, you're likely going to want to migrate to new std:: functionality when it's available anyway.

The boost stuff is generally pretty good, looks like it's used in the implementation of a released Boost library. I've also been tempted to use that implementation a few times.

I'd go for it.

Carpo answered 28/7, 2009 at 21:10 Comment(0)
P
0

You could also look at libsync for inspiration from http://www.ioremap.net/node/224 , which is quite new (maybe too new), but it is being used in the Elliptics Network so it does get (some?) testing.

It also gives you higher level primitives next to CAS: RCU (Read Copy Update) for lockless synchronisation between threads.

But it depends on what you mean by 'portable': it supports archtectures x86 and PPC, OSes Linux, FreeBSD, OpenBSD, Solaris and MacOSX but ... no Windows.

And the license is GPL, which you can hate or love.

Pease answered 29/7, 2009 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.