Skip to content

Commit 05cfb5c

Browse files
committed
feat(ntp): update NTP time service singleton
Refactor the NTP time service to use the eternal singleton pattern with optional DLL support. Add an ODR test target covering DLL singleton macros and adjust test setup.
1 parent 82e1d28 commit 05cfb5c

File tree

5 files changed

+85
-21
lines changed

5 files changed

+85
-21
lines changed

include/time_shield/ntp_time_service.hpp

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,42 @@ namespace time_shield {
179179
};
180180
#endif // _TIME_SHIELD_TEST_FAKE_NTP
181181

182-
#ifndef TIME_SHIELD_CPP17
183182
#if defined(TIME_SHIELD_TEST_FAKE_NTP)
184183
using RunnerAlias = detail::FakeNtpRunner;
185184
#else
186185
using RunnerAlias = NtpClientPoolRunner;
187186
#endif
188187

189-
extern NtpTimeServiceT<RunnerAlias> g_ntp_time_service;
190-
#endif // !TIME_SHIELD_CPP17
188+
#if defined(TIME_SHIELD_NTP_TIME_SERVICE_USE_DLL_SINGLETON)
189+
#if defined(_WIN32) || defined(__CYGWIN__)
190+
#ifdef TIME_SHIELD_NTP_TIME_SERVICE_DLL_EXPORTS
191+
#define TIME_SHIELD_NTP_TIME_SERVICE_API __declspec(dllexport)
192+
#else
193+
#define TIME_SHIELD_NTP_TIME_SERVICE_API __declspec(dllimport)
194+
#endif
195+
#else
196+
#define TIME_SHIELD_NTP_TIME_SERVICE_API
197+
#endif
198+
199+
extern "C" TIME_SHIELD_NTP_TIME_SERVICE_API NtpTimeServiceT<RunnerAlias>& ntp_time_service_instance() noexcept;
200+
#endif
201+
202+
template <class RunnerT>
203+
struct NtpTimeServiceSingleton final {
204+
static NtpTimeServiceT<RunnerT>& instance() noexcept {
205+
static NtpTimeServiceT<RunnerT>* p_instance = new NtpTimeServiceT<RunnerT>{};
206+
return *p_instance;
207+
}
208+
};
209+
210+
#if defined(TIME_SHIELD_NTP_TIME_SERVICE_USE_DLL_SINGLETON)
211+
template <>
212+
struct NtpTimeServiceSingleton<RunnerAlias> final {
213+
static NtpTimeServiceT<RunnerAlias>& instance() noexcept {
214+
return ntp_time_service_instance();
215+
}
216+
};
217+
#endif
191218
} // namespace detail
192219

193220
/// \ingroup ntp
@@ -202,11 +229,7 @@ namespace time_shield {
202229
/// \brief Return the singleton instance.
203230
/// \return Singleton instance.
204231
static NtpTimeServiceT& instance() noexcept {
205-
#ifdef TIME_SHIELD_CPP17
206-
return m_instance;
207-
#else
208-
return detail::g_ntp_time_service;
209-
#endif
232+
return detail::NtpTimeServiceSingleton<RunnerT>::instance();
210233
}
211234

212235
NtpTimeServiceT(const NtpTimeServiceT&) = delete;
@@ -532,21 +555,14 @@ namespace time_shield {
532555

533556
std::unique_ptr<RunnerT> m_runner;
534557

535-
#ifdef TIME_SHIELD_CPP17
536-
static NtpTimeServiceT m_instance;
537-
#endif
538558
};
539559

540-
#ifdef TIME_SHIELD_CPP17
541-
template <class RunnerT>
542-
inline NtpTimeServiceT<RunnerT> NtpTimeServiceT<RunnerT>::m_instance{};
543-
#endif
544-
545-
#ifndef TIME_SHIELD_CPP17
560+
#if defined(TIME_SHIELD_NTP_TIME_SERVICE_USE_DLL_SINGLETON) && defined(TIME_SHIELD_NTP_TIME_SERVICE_DLL_IMPLEMENTATION)
546561
namespace detail {
547-
#if defined(TIME_SHIELD_NTP_TIME_SERVICE_DEFINE)
548-
NtpTimeServiceT<RunnerAlias> g_ntp_time_service;
549-
#endif
562+
extern "C" TIME_SHIELD_NTP_TIME_SERVICE_API NtpTimeServiceT<RunnerAlias>& ntp_time_service_instance() noexcept {
563+
static NtpTimeServiceT<RunnerAlias>* p_instance = new NtpTimeServiceT<RunnerAlias>{};
564+
return *p_instance;
565+
}
550566
} // namespace detail
551567
#endif
552568

tests/ntp_time_service_test.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#if TIME_SHIELD_ENABLE_NTP_CLIENT
44
#define TIME_SHIELD_TEST_FAKE_NTP
5-
#define TIME_SHIELD_NTP_TIME_SERVICE_DEFINE
65
#include <time_shield/ntp_time_service.hpp>
76

87
#include <cassert>

tests/odr/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,14 @@ target_link_libraries(odr_cxx17 PRIVATE time_shield::time_shield)
1414
set_target_properties(odr_cxx17 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES)
1515

1616
add_test(NAME odr_cxx17 COMMAND odr_cxx17)
17+
18+
set(NTP_TIME_SERVICE_DLL_SOURCES
19+
ntp_time_service_dll_a.cpp
20+
ntp_time_service_dll_b.cpp
21+
)
22+
23+
add_executable(ntp_time_service_dll_odr ${NTP_TIME_SERVICE_DLL_SOURCES})
24+
target_link_libraries(ntp_time_service_dll_odr PRIVATE time_shield::time_shield)
25+
set_target_properties(ntp_time_service_dll_odr PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES)
26+
27+
add_test(NAME ntp_time_service_dll_odr COMMAND ntp_time_service_dll_odr)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <time_shield/config.hpp>
2+
3+
#if TIME_SHIELD_ENABLE_NTP_CLIENT
4+
#define TIME_SHIELD_TEST_FAKE_NTP
5+
#define TIME_SHIELD_NTP_TIME_SERVICE_USE_DLL_SINGLETON
6+
#define TIME_SHIELD_NTP_TIME_SERVICE_DLL_EXPORTS
7+
#define TIME_SHIELD_NTP_TIME_SERVICE_DLL_IMPLEMENTATION
8+
#include <time_shield/ntp_time_service.hpp>
9+
10+
int ntp_time_service_dll_helper();
11+
12+
int main() {
13+
auto& service = time_shield::NtpTimeService::instance();
14+
service.shutdown();
15+
(void)ntp_time_service_dll_helper();
16+
return 0;
17+
}
18+
#else
19+
int main() {
20+
return 0;
21+
}
22+
#endif
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <time_shield/config.hpp>
2+
3+
#if TIME_SHIELD_ENABLE_NTP_CLIENT
4+
#define TIME_SHIELD_TEST_FAKE_NTP
5+
#define TIME_SHIELD_NTP_TIME_SERVICE_USE_DLL_SINGLETON
6+
#define TIME_SHIELD_NTP_TIME_SERVICE_DLL_EXPORTS
7+
#include <time_shield/ntp_time_service.hpp>
8+
9+
int ntp_time_service_dll_helper() {
10+
return time_shield::NtpTimeService::instance().running() ? 1 : 0;
11+
}
12+
#else
13+
int ntp_time_service_dll_helper() {
14+
return 0;
15+
}
16+
#endif

0 commit comments

Comments
 (0)