atomic : is_lock_free

Jul 13, 2016 at 5:32am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//I can not get the significance of 'is_lock_free'
#define _ENABLE_ATOMIC_ALIGNMENT_FIX
#include  <atomic>
#include <iostream>
#include <string>
#include <type_traits>
class A
{
	int a;
	int b;
};
int main()
{
	std::atomic_char ac;
	std::atomic<A> aa;
	std::atomic<unsigned long long> aull;
	std::cout << std::boolalpha;
	//all are true
	std::cout << ac.is_lock_free()   << std::endl;//true
	std::cout << aa.is_lock_free()   << std::endl;//true
	std::cout << aull.is_lock_free() << std::endl;//true
	std::cin.get();
}

Jul 13, 2016 at 6:28am
is_lock_free() evaluates to true if atomic operations on the type are lock-free.

In simplified terms, this means that lock-free atomic CPU instructions are used to enforce atomicity (no secondary locking mechanisms like mutexes are involved).
Jul 13, 2016 at 8:46am
can give a 'false' example?
Jul 13, 2016 at 8:47am
the is_lock_free()'s result is false?
Jul 13, 2016 at 9:44am
> can give a 'false' example?

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <utility>
#include <atomic>

int main()
{
    struct A { int i = 0 ; double d = 9 ; char c[100] {} ; };
    
    std::cout << "    A is trivially copyable? " << std::boolalpha << std::is_trivially_copyable<A>::value << '\n' // true
              << "std::atomic<A> is lock free? " << std::boolalpha << std::atomic<A>{}.is_lock_free() << '\n' ; // false
}

http://coliru.stacked-crooked.com/a/78f0417a5f8dbbed
http://rextester.com/QAJ28098

Note: clang++/libc++ and g++/libstdc++ on Linux have dependency on libatomic. (Need to link with -latomic.)
Last edited on Jul 13, 2016 at 9:47am
Jul 14, 2016 at 12:42am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define _ENABLE_ATOMIC_ALIGNMENT_FIX
#include <iostream>
#include <utility>
#include <atomic>
struct A1
{
	long long i : 32;
	long long j : 32;
};
struct A2
{
	long long i : 32;
	long long j : 32;
	long long k : 1;
};
int main()
{
	//on window10, vs2015

	//64 bit is the standard?
	std::cout << std::boolalpha;
	std::cout << "std::atomic<A1>{}.is_lock_free():" << std::atomic<A1>{}.is_lock_free() << ";sizeof(A1):" << sizeof(A1) << std::endl;
	std::cout << "std::atomic<A2>{}.is_lock_free():" << std::atomic<A2>{}.is_lock_free() << ";sizeof(A2):" << sizeof(A2) << std::endl;
	std::cin.get();
}
Jul 14, 2016 at 1:58am
> 64 bit is the standard?

No.

What can be atomic lock-free depends on the processor architecture
(in practice it depends on both the size and the alignment of the trivially copyable atomic object).

The subset of what is actually atomic lock-free depends on the quality of implementation
note: the C++ standard does not require that sizeof( std::atomic<T> ) must be equal to sizeof(T)

libc++ (FreeBSD)
1
2
3
static inline bool __c11_atomic_is_lock_free(size_t __size) {
    return __atomic_is_lock_free(__size, 0);
}

https://svnweb.freebsd.org/base/release/10.3.0/contrib/libc%2B%2B/include/atomic?revision=297553&view=markup#l626
1
2
3
4
5
6
7
8
9
10
struct __atomic_base  // false
{
    // ...
    bool is_lock_free() const volatile _NOEXCEPT
    {return __c11_atomic_is_lock_free(sizeof(_Tp));}
    // ...
    bool is_lock_free() const _NOEXCEPT
    {return __c11_atomic_is_lock_free(sizeof(_Tp));}
    // ...
};

https://svnweb.freebsd.org/base/release/10.3.0/contrib/libc%2B%2B/include/atomic?revision=297553&view=markup#l814

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <atomic>
#include <iomanip>

template < std::size_t N > void test() 
{
    struct A { char c[N] {} ; } ;
    std::cout << std::setw(6) << sizeof(A) << std::setw(15)  << sizeof( std::atomic<A> ) 
              << "                  " << std::atomic<A>{}.is_lock_free() << '\n' ;
}

int main()
{
    std::cout << "sizeof(T)   sizeof( std::atomic<T> ) is_lock_free\n" 
              << "-------------------------------------------------\n\n" << std::boolalpha ;
              
    test<3>() ;
    test<4>() ;
    
    test<5>() ;
    test<8>() ;
    
    test<9>() ;
    test<16>() ;
}

-------- clang++/libc++ --------


sizeof(T)   sizeof( std::atomic<T> ) is_lock_free
-------------------------------------------------

     3              4                  true
     4              4                  true
     5              8                  true
     8              8                  true
     9             16                  false
    16             16                  true

-------- g++/libstdc++ --------


sizeof(T)   sizeof( std::atomic<T> ) is_lock_free
-------------------------------------------------

     3              3                  false
     4              4                  true
     5              5                  false
     8              8                  true
     9              9                  false
    16             16                  true 

http://coliru.stacked-crooked.com/a/3163e75f372c1ba7

Hmm.... clang++ pads up size 9 to size 16, and then turns around and says that it is not lock-free.
Jul 15, 2016 at 1:39am
Thanks. It is so complex!
Topic archived. No new replies allowed.