1
\$\begingroup\$

I recently was reading an article labeled "Modern C++ Singleton Template". The proposed solution used C++11 feature of Magic Statics (N2660). I wanted to adapt it for an own project in "freestanding" (fno-hosted) environment.

My code looks as follows:

Singleton.hpp

namespace std
{
 template <typename T>
 class Singleton
 {
 public:
 // = initialization and termination methods
 Singleton( const Singleton& ) = delete; // copy constructor
 Singleton( Singleton&& ) = delete; // move constructor
 Singleton& operator=( const Singleton& ) = delete; // assignment operator
 Singleton& operator=( Singleton&&) = delete; // copy move operator
 // = accessor methods.
 static T& getInstance();
 protected:
 Singleton() {}; // default constructor
 ~Singleton() {}; // default destructor
 struct Token {};
 private:
 }; // end template class T
 template <typename T>
 T& Singleton<T>::getInstance()
 {
 static T __singleInstance( Token{} ); 
 return( __singleInstance );
 } // end public method 'getInstance()'
} // end namespace std

Test.hpp

#include "libs/libc++/singleton.hpp" // declaration of template class 'Singleton'
class Test final : public TestSingelton<Test>
{
 public:
 Test(TestToken);
 ~Test();
 void use();
};

Test.cpp

Test::Test(TestToken)
{
 logTraceEvent_m( loging to file );
}
Test::~Test()
{
 logTraceEvent_m( loging to file );
}
void 
Test::use()
{
 logTraceEvent_m( loging to file );
}

Problem

In hosted environment (Linux, GCC 7.5.0) it works as presented in the article refereed to above. The static variable is initialized only once; the constructor of the derived class is called only once.

Entering main()
Entering a()
constructed
in use
Entering b()
in use
Leaving main()
destructed

However, in my "-ffreestandig" environment it is not working. "freestanding" = kernel without any standard headers; without any libraries!

Static variable ("__singleInstance") is initialized on every call to "Test::getInstance()".

______ TRACE: constructor = Test::Test(TestSingelton<Test>::TestToken), ...
______ TRACE: use = void Test::use(), file = test/Test.cpp, line = 37.
______ TRACE: constructor = Test::Test(TestSingelton<Test>::TestToken), ...
______ TRACE: use = void Test::use(), file = test/Test.cpp, line = 37.

What I'm doing wrong? Is there any advice in which direction I have to investigate?

  • compiler options?
  • -W -Wall -pedantic -ffreestanding -std=gnu++17 -fno-PIC -fno-exceptions -fno-rtti -fno-use-cxa-atexit -march=native -m64 -mcmodel=kernel -mno-red-zone -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-sse4a -mno-3dnow -mno-avx -mno-avx2
  • runtime environment, that is missing something
asked Nov 18, 2020 at 14:17
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Your test code doesn't match your test output. "Test.cpp" isn't even valid C++ code!

How does your massive amount of code do anything significantly different from the following eight lines?

template<class T>
struct Singleton {
 struct Token {};
 static T& getInstance() {
 static T instance(Token{});
 return instance;
 }
};

Example usage:

struct Widget { explicit Widget(Singleton<Widget>::Token); };
Widget& example = Singleton<Widget>::getInstance();

As for why the "thread-safe statics" feature doesn't work on your freestanding platform, I would suspect it's because your freestanding platform doesn't support thread-safe statics. :) Check the documentation for your toolchain to see how static variables are handled on that particular platform.

answered Nov 19, 2020 at 1:01
\$\endgroup\$
0
\$\begingroup\$

After further thinking and reading I suspect the behaviour is caused by my incomplete C++ ABI. My functions __xca_gaurd_aquire/__xca_guard_release are currently empty functions and I will go ahead to implement minimalistic versions and see if I get different results. Currently I belive that's the way to overcome my problem.

answered Nov 19, 2020 at 6:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.