Skip to content

Commit 9bb2edf

Browse files
committed
Merge branch 'pull-request/#1002-Add-singleton_base' into development
# Conflicts: # .gitignore # include/etl/file_error_numbers.h
2 parents 3d43922 + c1a1d24 commit 9bb2edf

File tree

11 files changed

+331
-1
lines changed

11 files changed

+331
-1
lines changed

include/etl/file_error_numbers.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,7 @@ SOFTWARE.
103103
#define ETL_EXPECTED_FILE_ID "70"
104104
#define ETL_ALIGNMENT_FILE_ID "71"
105105
#define ETL_BASE64_FILE_ID "72"
106-
#define ETL_UNALIGNED_TYPE_FILE_ID "73"
106+
#define ETL_SINGLETON_BASE_FILE_ID "73"
107+
108+
#define ETL_UNALIGNED_TYPE_FILE_ID "74"
107109
#endif

include/etl/singleton_base.h

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
///\file
2+
3+
/******************************************************************************
4+
The MIT License(MIT)
5+
6+
Embedded Template Library.
7+
https://github.com/ETLCPP/etl
8+
https://www.etlcpp.com
9+
10+
Copyright(c) 2019 John Wellbelove
11+
Copyright(c) 2024 BMW AG
12+
13+
Permission is hereby granted, free of charge, to any person obtaining a copy
14+
of this software and associated documentation files(the "Software"), to deal
15+
in the Software without restriction, including without limitation the rights
16+
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
17+
copies of the Software, and to permit persons to whom the Software is
18+
furnished to do so, subject to the following conditions :
19+
20+
The above copyright notice and this permission notice shall be included in all
21+
copies or substantial portions of the Software.
22+
23+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
26+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
SOFTWARE.
30+
******************************************************************************/
31+
32+
#ifndef ETL_SINGLETON_BASE_INCLUDED
33+
#define ETL_SINGLETON_BASE_INCLUDED
34+
35+
///\defgroup singleton_base singleton_base
36+
/// Templated version of the singleton pattern, implemented as base class
37+
/// for singletons.
38+
///\ingroup etl
39+
40+
#include "platform.h"
41+
#include "error_handler.h"
42+
#include "nullptr.h"
43+
#include "file_error_numbers.h"
44+
45+
namespace etl
46+
{
47+
//*************************************************************************
48+
/// Base singleton error exception.
49+
//*************************************************************************
50+
class singleton_base_exception : public etl::exception
51+
{
52+
public:
53+
54+
singleton_base_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
55+
: exception(reason_, file_name_, line_number_)
56+
{
57+
}
58+
};
59+
60+
//*************************************************************************
61+
/// Singleton not created error exception.
62+
//*************************************************************************
63+
class singleton_base_not_created : public etl::singleton_base_exception
64+
{
65+
public:
66+
67+
singleton_base_not_created(string_type file_name_, numeric_type line_number_)
68+
: singleton_base_exception(ETL_ERROR_TEXT("singleton_base:not created", ETL_SINGLETON_BASE_FILE_ID"A"), file_name_, line_number_)
69+
{
70+
}
71+
};
72+
73+
//*************************************************************************
74+
/// Singleton instance already exists.
75+
//*************************************************************************
76+
class singleton_base_already_created : public etl::singleton_base_exception
77+
{
78+
public:
79+
80+
singleton_base_already_created(string_type file_name_, numeric_type line_number_)
81+
: singleton_base_exception(ETL_ERROR_TEXT("singleton_base:already created", ETL_SINGLETON_BASE_FILE_ID"A"), file_name_, line_number_)
82+
{
83+
}
84+
};
85+
86+
//***********************************************************************
87+
/// Base class for singletons.
88+
/// \tparam T Any type that wants to expose the instance() interface.
89+
///
90+
/// This class is designed to work as a generic base class for any class that wants to
91+
/// provide a singleton interface. It'll also work for classes that do not have a
92+
/// default constructor.
93+
///
94+
/// Usage example:
95+
///
96+
/// class Origin
97+
/// : singleton<Origin>
98+
/// {
99+
/// public:
100+
/// Origin(int x, int y)
101+
/// : singleton<Origin>(*this)
102+
/// {}
103+
///
104+
/// int getX() const;
105+
/// } theOrigin(0, 0);
106+
///
107+
/// int x = Origin::instance().getX();
108+
///
109+
///
110+
/// Note:
111+
///
112+
/// It is important that a call to instance() will not create the instance of the class. It needs
113+
/// to be created by the user before calling instance(). This way, the user has better control
114+
/// over the instance lifetime instead of e.g. lazy initialization.
115+
//***********************************************************************
116+
template <typename T>
117+
class singleton_base
118+
{
119+
public:
120+
121+
//***********************************************************************
122+
// Returns a reference to the instance.
123+
//***********************************************************************
124+
static T& instance()
125+
{
126+
ETL_ASSERT(m_self != ETL_NULLPTR, ETL_ERROR(etl::singleton_base_not_created));
127+
128+
return *m_self;
129+
}
130+
131+
//***********************************************************************
132+
/// Returns whether an instance has been attached to singleton<T> or not.
133+
//***********************************************************************
134+
static bool is_valid()
135+
{
136+
return (m_self != ETL_NULLPTR);
137+
}
138+
139+
protected:
140+
141+
//***********************************************************************
142+
/// Constructs the instance of singleton.
143+
/// theInstance Reference to T, which will be returned when instance() is called.
144+
//***********************************************************************
145+
explicit singleton_base(T& theInstance)
146+
{
147+
ETL_ASSERT(m_self == ETL_NULLPTR, ETL_ERROR(etl::singleton_base_already_created));
148+
149+
m_self = &theInstance;
150+
}
151+
152+
//***********************************************************************
153+
/// Removes the internal reference to the instance passed in the constructor.
154+
//***********************************************************************
155+
~singleton_base()
156+
{
157+
m_self = ETL_NULLPTR;
158+
}
159+
160+
private:
161+
162+
static T* m_self;
163+
};
164+
165+
//***********************************************************************
166+
/// No violation of one definition rule as this is a class template
167+
//***********************************************************************
168+
template<class T>
169+
T* singleton_base<T>::m_self = ETL_NULLPTR;
170+
}
171+
172+
#endif

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ add_executable(etl_tests
233233
test_set.cpp
234234
test_shared_message.cpp
235235
test_singleton.cpp
236+
test_singleton_base.cpp
236237
test_smallest.cpp
237238
test_span_dynamic_extent.cpp
238239
test_span_fixed_extent.cpp

test/syntax_check/c++03/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ target_sources(t98 PRIVATE etl_profile.h
260260
../set.h.t.cpp
261261
../shared_message.h.t.cpp
262262
../singleton.h.t.cpp
263+
../singleton_base.h.t.cpp
263264
../smallest.h.t.cpp
264265
../span.h.t.cpp
265266
../sqrt.h.t.cpp

test/syntax_check/c++11/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ target_sources(t11 PRIVATE etl_profile.h
260260
../set.h.t.cpp
261261
../shared_message.h.t.cpp
262262
../singleton.h.t.cpp
263+
../singleton_base.h.t.cpp
263264
../smallest.h.t.cpp
264265
../span.h.t.cpp
265266
../sqrt.h.t.cpp

test/syntax_check/c++14/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ target_sources(t14 PRIVATE etl_profile.h
260260
../set.h.t.cpp
261261
../shared_message.h.t.cpp
262262
../singleton.h.t.cpp
263+
../singleton_base.h.t.cpp
263264
../smallest.h.t.cpp
264265
../span.h.t.cpp
265266
../sqrt.h.t.cpp

test/syntax_check/c++17/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ target_sources(t17 PRIVATE etl_profile.h
260260
../set.h.t.cpp
261261
../shared_message.h.t.cpp
262262
../singleton.h.t.cpp
263+
../singleton_base.h.t.cpp
263264
../smallest.h.t.cpp
264265
../span.h.t.cpp
265266
../sqrt.h.t.cpp

test/syntax_check/c++20/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ target_sources(t20 PRIVATE etl_profile.h
260260
../set.h.t.cpp
261261
../shared_message.h.t.cpp
262262
../singleton.h.t.cpp
263+
../singleton_base.h.t.cpp
263264
../smallest.h.t.cpp
264265
../span.h.t.cpp
265266
../sqrt.h.t.cpp
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/******************************************************************************
2+
The MIT License(MIT)
3+
4+
Embedded Template Library.
5+
https://github.com/ETLCPP/etl
6+
https://www.etlcpp.com
7+
8+
Copyright(c) 2024 John Wellbelove
9+
10+
Permission is hereby granted, free of charge, to any person obtaining a copy
11+
of this software and associated documentation files(the "Software"), to deal
12+
in the Software without restriction, including without limitation the rights
13+
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14+
copies of the Software, and to permit persons to whom the Software is
15+
furnished to do so, subject to the following conditions :
16+
17+
The above copyright notice and this permission notice shall be included in all
18+
copies or substantial portions of the Software.
19+
20+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26+
SOFTWARE.
27+
******************************************************************************/
28+
29+
#include <etl/singleton_base.h>

test/test_singleton_base.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/******************************************************************************
2+
The MIT License(MIT)
3+
4+
Embedded Template Library.
5+
https://github.com/ETLCPP/etl
6+
https://www.etlcpp.com
7+
8+
Copyright(c) 2022 John Wellbelove
9+
Copyright(c) 2024 BMW AG
10+
11+
Permission is hereby granted, free of charge, to any person obtaining a copy
12+
of this software and associated documentation files(the "Software"), to deal
13+
in the Software without restriction, including without limitation the rights
14+
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
15+
copies of the Software, and to permit persons to whom the Software is
16+
furnished to do so, subject to the following conditions :
17+
18+
The above copyright notice and this permission notice shall be included in all
19+
copies or substantial portions of the Software.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
SOFTWARE.
28+
******************************************************************************/
29+
30+
#include "unit_test_framework.h"
31+
32+
#include "etl/singleton_base.h"
33+
34+
#include <string>
35+
#include <type_traits>
36+
37+
class Test_Singleton: public etl::singleton_base<Test_Singleton>
38+
{
39+
public:
40+
41+
Test_Singleton(int i_, std::string text_)
42+
: ::etl::singleton_base<Test_Singleton>(*this)
43+
, i(i_)
44+
, text(text_)
45+
{
46+
}
47+
48+
void Increment()
49+
{
50+
++i;
51+
text += "*";
52+
}
53+
54+
int i;
55+
std::string text;
56+
};
57+
58+
namespace
59+
{
60+
SUITE(test_singleton)
61+
{
62+
//*************************************************************************
63+
TEST(test1)
64+
{
65+
CHECK(!Test_Singleton::is_valid());
66+
CHECK_THROW(Test_Singleton::instance(), etl::singleton_base_not_created);
67+
68+
{
69+
Test_Singleton singleton(1, "Start:");
70+
CHECK(Test_Singleton::is_valid());
71+
72+
Test_Singleton& ts = Test_Singleton::instance();
73+
74+
CHECK_EQUAL(1, ts.i);
75+
CHECK_EQUAL("Start:", ts.text);
76+
77+
ts.Increment();
78+
79+
CHECK_EQUAL(2, ts.i);
80+
CHECK_EQUAL("Start:*", ts.text);
81+
82+
Test_Singleton* pts = &Test_Singleton::instance();
83+
84+
CHECK_EQUAL(2, ts.i);
85+
CHECK_EQUAL(2, pts->i);
86+
CHECK_EQUAL("Start:*", ts.text);
87+
CHECK_EQUAL("Start:*", pts->text);
88+
89+
pts->Increment();
90+
91+
CHECK_EQUAL(3, ts.i);
92+
CHECK_EQUAL(3, pts->i);
93+
CHECK_EQUAL("Start:**", ts.text);
94+
CHECK_EQUAL("Start:**", pts->text);
95+
96+
CHECK_THROW(Test_Singleton(2, "XYZ"), etl::singleton_base_already_created);
97+
}
98+
99+
CHECK(!Test_Singleton::is_valid());
100+
CHECK_THROW(Test_Singleton::instance(), etl::singleton_base_not_created);
101+
}
102+
}
103+
}
104+

0 commit comments

Comments
 (0)