1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /***************************************************************************
3  *            atomic.cc
4  *
5  *  Wed Mar 23 09:17:12 CET 2016
6  *  Copyright 2016 Christian Gl�ckner
7  *  cgloeckner@freenet.de
8  ****************************************************************************/
9 
10 /*
11  *  This file is part of DrumGizmo.
12  *
13  *  DrumGizmo is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU Lesser General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  DrumGizmo is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU Lesser General Public License for more details.
22  *
23  *  You should have received a copy of the GNU Lesser General Public License
24  *  along with DrumGizmo; if not, write to the Free Software
25  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
26  */
27 #include <uunit.h>
28 
29 #include <atomic.h>
30 
31 class AtomicTest
32 	: public uUnit
33 {
34 public:
AtomicTest()35 	AtomicTest()
36 	{
37 		uUNIT_TEST(AtomicTest::podAtomicsUseStandardImpl);
38 		uUNIT_TEST(AtomicTest::nonPodAtomicsUseOwnImpl);
39 		uUNIT_TEST(AtomicTest::podAtomicCanBeDefaultInitialized);
40 		uUNIT_TEST(AtomicTest::nonPodAtomicCanBeDefaultInitialized);
41 		uUNIT_TEST(AtomicTest::podAtomicCanBeValueInitialized);
42 		uUNIT_TEST(AtomicTest::nonPodAtomicCanBeValueInitialized);
43 		uUNIT_TEST(AtomicTest::podAtomicCanBeValueAssigned);
44 		uUNIT_TEST(AtomicTest::nonPodAtomicCanBeValueAssigned);
45 		uUNIT_TEST(AtomicTest::podAtomicsAreLockFree);
46 	}
47 
podAtomicsUseStandardImpl()48 	void podAtomicsUseStandardImpl()
49 	{
50 		uUNIT_ASSERT(isUsingStandardImpl<bool>());
51 		uUNIT_ASSERT(isUsingStandardImpl<unsigned short int>());
52 		uUNIT_ASSERT(isUsingStandardImpl<short int>());
53 		uUNIT_ASSERT(isUsingStandardImpl<unsigned int>());
54 		uUNIT_ASSERT(isUsingStandardImpl<int>());
55 		uUNIT_ASSERT(isUsingStandardImpl<unsigned long int>());
56 		uUNIT_ASSERT(isUsingStandardImpl<long int>());
57 		uUNIT_ASSERT(isUsingStandardImpl<unsigned long long int>());
58 		uUNIT_ASSERT(isUsingStandardImpl<long long int>());
59 		uUNIT_ASSERT(isUsingStandardImpl<float>());
60 		uUNIT_ASSERT(isUsingStandardImpl<double>());
61 		uUNIT_ASSERT(isUsingStandardImpl<long double>());
62 	}
63 
nonPodAtomicsUseOwnImpl()64 	void nonPodAtomicsUseOwnImpl()
65 	{
66 		uUNIT_ASSERT(!isUsingStandardImpl<std::string>());
67 	}
68 
podAtomicCanBeDefaultInitialized()69 	void podAtomicCanBeDefaultInitialized()
70 	{
71 		Atomic<int> i;
72 		// note: i is initialized with garbage
73 		(void)i; // prevent compiler 'unused' warning
74 	}
75 
nonPodAtomicCanBeDefaultInitialized()76 	void nonPodAtomicCanBeDefaultInitialized()
77 	{
78 		Atomic<std::string> s;
79 		uUNIT_ASSERT_EQUAL(s.load(), std::string{});
80 	}
81 
podAtomicCanBeValueInitialized()82 	void podAtomicCanBeValueInitialized()
83 	{
84 		Atomic<int> i{5};
85 		uUNIT_ASSERT_EQUAL(i.load(), 5);
86 	}
87 
nonPodAtomicCanBeValueInitialized()88 	void nonPodAtomicCanBeValueInitialized()
89 	{
90 		Atomic<std::string> s{"hello world"};
91 		uUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"});
92 	}
93 
podAtomicCanBeValueAssigned()94 	void podAtomicCanBeValueAssigned()
95 	{
96 		Atomic<int> i;
97 		i = 5;
98 		uUNIT_ASSERT_EQUAL(i.load(), 5);
99 	}
100 
nonPodAtomicCanBeValueAssigned()101 	void nonPodAtomicCanBeValueAssigned()
102 	{
103 		Atomic<std::string> s;
104 		s = "hello world";
105 		uUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"});
106 	}
107 
podAtomicsAreLockFree()108 	void podAtomicsAreLockFree()
109 	{
110 		uUNIT_ASSERT(isLockFree<bool>());
111 		uUNIT_ASSERT(isLockFree<unsigned short int>());
112 		uUNIT_ASSERT(isLockFree<short int>());
113 		uUNIT_ASSERT(isLockFree<unsigned int>());
114 		uUNIT_ASSERT(isLockFree<int>());
115 		uUNIT_ASSERT(isLockFree<unsigned long int>());
116 		uUNIT_ASSERT(isLockFree<long int>());
117 		uUNIT_ASSERT(isLockFree<float>());
118 		uUNIT_ASSERT(isLockFree<std::size_t>());
119 
120 		// NOTE: Not lock free on small systems
121 		//uUNIT_ASSERT(isLockFree<unsigned long long int>());
122 		//uUNIT_ASSERT(isLockFree<long long int>());
123 		//uUNIT_ASSERT(isLockFree<double>());
124 		//uUNIT_ASSERT(isLockFree<long double>());
125 	}
126 
127 private:
128 	template <typename T>
isUsingStandardImpl()129 	bool isUsingStandardImpl()
130 	{
131 		return std::is_base_of<std::atomic<T>, Atomic<T>>::value;
132 	}
133 
134 	template <typename T>
isLockFree()135 	bool isLockFree()
136 	{
137 		Atomic<T> a;
138 		return a.is_lock_free();
139 	}
140 };
141 
142 // Registers the fixture into the 'registry'
143 static AtomicTest test;
144