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
\$\endgroup\$
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.

\$\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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.