Additional Atomics Errata

ISO/IEC JTC1 SC22 WG14 N1484 – 2010-05-26

Lawrence Crowl, crowl@google.com
Paul E. McKenney, paulmck@linux.vnet.ibm.com

Introduction

This document lists some additional errata in the specification of the atomics in the current working draft (n1425, along with proposed wording for their correction. It is based on n1477.

Errata

The list of errata is as follows:

  1. C-language unions must be prohibited from containing atomic members, given that it is not possible to provide constructors for unions in the C language.
  2. The example of weak compare-and-exchange needs to actually use the weak form of the primitive.

Unions and atomic members

It is not necessarily obvious that the C++ Working Draft wording implies that inclusion of atomics in a C-language union results in undefined behavior. This section therefore lists the statements in the C++ Working Draft that imply this conclusion, taken from an email from Lawrence.

Section 9.5p2 reads as follows:

A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non-static data member of reference type the program is ill-formed. At most one non-static data member of a union may have a brace-or-equal-initializer. [ Note: if any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]

This note elaborates the normative language found in Section 12.8p12:

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:

— a variant member with a non-trivial corresponding constructor and X is a union-like class

In other words, if a member of the union has non-trivial copy constructors and non-trivial copy assignment operators, the user must supply the corresponding member function. However, the C language provides no way to supply such member functions.

Section 29.5.1 lists the following declarations for integral types:

atomic_bool(const atomic_bool&) = delete;
atomic_bool& operator=(const atomic_bool&) = delete;
atomic_bool& operator=(const atomic_bool&) volatile = delete;

Similar declaration appear for the other atomic types. These declarations imply that the atomic types have non-trivial copy constructors and non-trivial copy assignment operators. Therefore, placing atomics in C-language unions is forbidden, which we can model as undefined behavior.

Wording

Section 6.7.3p2

New paragraph following Section 6.7.2.1p16:

This new paragraph notes that placing atomics in C-languages unions results in undefined behavior:

If a union contains an atomic object, undefined behavior ensues.

Section 7.16.6.4p6

The example in this paragraph uses a function atomic_compare_exchange() that is not defined in this standard. This needs to change to use atomic_compare_exchange_weak() as shown below:

EXAMPLE: A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop.

expected = atomic_load(&current);
do desired = function(expected);
while (!atomic_compare_exchange_weak(&current, &expected, desired));

When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable.