Implicit Conversion Operators for Atomics

ISO/IEC JTC1 SC22 WG21 N2514 = 08-0024 - 2008-02-01

Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org

Introduction

The early proposals for atomics, culminating in N2324, provided for implicit conversions from an atomic type to the corresponding base type as a more syntactically concise method for specifying the load operation.

Because of the problems with implicit conversions, the library subcommittee directed their removal from the atomics proposal, which was reflected in N2324 and that paper's final version, N2427, and is reflected in the current working draft standard, N2461.

However, there is substantial support among members of the committee to reverse that decision and add implicit conversions back into atomics. This paper clarifies the issues and provides normative wording for such a change.

Issue Discussion

Within this discussion, implict conversion operators yielding the base type of an atomic type will be called implicit loads. Calling one of load functions will be called an explicit load.

Ambiguity and Insecurity

The general use of implicit conversions has caused significant ambiguities and insecurities in working code. Such problems are described in N1952 and its successors, most recently N2437. However, a common feature of these problems is that the conversion returns an attribute of the object. As examples, string_type::operator const char* returns a representation address and smart_pointer::operator bool returns the result of a test for null.

In contrast, the implicit load defined in N2324 returns an alternate representation of the atomic's abstract value. Indeed, as the atomic types have deleted copy constructors and no other operations returning atomics, there is no other representation of the abstract value of the atomic.

Furthermore, as the atomic types have deleted copy constructors, user-defined functions cannot have them as parameters or return types. Thus, there can be no additional potential ambiguity in calls to such functions with arguments formed from explicit loads.

In summary, atomic objects are only lvalues, never rvalues. So, while use of implicit conversion operators should usually be viewed with suspicion, the proposed use in atomics introduces no problems.

Implicit Load Hides Cost

Implicit load makes the cost of an atomic load essentially invisible in the source. As atomic loads can be expensive, the invisibility of the cost can thus lead programmers to write code that is significantly more expensive than necessary.

The situation is similar for the assignment operator, which allows minimal, but not invisible, syntax for an atomic store operation.

Implicit Load Encourages Errors

Related to the hidden cost of implicit load, is the hidden semantic implications of reading an atomic variable more than once. Algorithms using atomic variables are much more likely to be correct if they read the variables only once. The additional syntactic burden of writing an explicit load both encourages minimizing the number of loads and makes multiple loads on the same variable more obvious.

The situation is less problematic for the assignment operator, as programmers are less likely to perform multiple assignments and as the operation has some explicit syntax.

Implicit Load Aids Presentations

In many contexts where code is presented, physical space is at a premium and non-essential details are unwelcome. In such contexts, presenters will be tempted to write implicit loads even if the language does not provide them. Such code will be syntactically incorrect, thus inhibiting compilation of examples and inhibiting the conversion of examples into working code.

Implicit Load Encourages SC-Focused Presentations

Presentations, articles, and papers will likely assume or require sequentially-consistent operations, which are often stronger than algorithms require. The consequences are that presented algorithms are more understandable but less efficient. This tradeoff manifests itself in both published papers on lock-free algorithms and on the adoption of those algorithms in real-world environments.

This SC focus is already present in the overloaded assignment and increment operators for atomics. The concern is the additional degree of focus.

Other Languages Have Implicit Load

Other programming languages, notably Java and C#, have implicit load. As a result, C++ programs without implicit load will look clumsier than other languages.

Proposed Wording

The following changes add implicit load to the atomics library.

29.4.1 (tentative) Integral Types [atomics.types.integral (tentative)]

To struct atomic_bool, add member:


operator bool() const volatile;

To struct atomic_itype, add member:


operator integral() const volatile;

29.4.2 (tentative) Address Type [atomics.types.address (tentative)]

To struct atomic_address, add member:


operator void*() const volatile;

29.4.3 (tentative) Generic Types [atomics.types.generic (tentative)]

To template struct atomic, add member:


operator T() const volatile;

To template struct atomic<integral> specializations, add member:


operator integral() const volatile;

To template struct atomic<T*> specializations, add member:


operator T*() const volatile;

29.4.4 (tentative) Operations [atomics.types.operatons (tentative)]

After paragraph 11, add the following specification.


A::operator C() const volatile;

Effects: load()

Returns: The result of load().