I was looking for a Singleton Qt implementation and found this. but I have some question about it.
What is the purpose of making create a QBasicAtomicPointer ?
What is the point in qCallOnce of using testAndSetRelaxed if previously we have used fetchAndStoreAcquire ? Isn't the acquire semantic already preventing any memory reordering after it ?
What is the purpose of the qCallOncePerThread function ? Isn't qCallOnce already thread-safe ?
I copy the contents of the suggested implementation here:
call_once.h
#ifndef CALL_ONCE_H
#define CALL_ONCE_H
#include <QtGlobal>
#include <QAtomicInt>
#include <QMutex>
#include <QWaitCondition>
#include <QThreadStorage>
#include <QThread>
namespace CallOnce {
enum ECallOnce {
CO_Request,
CO_InProgress,
CO_Finished
};
Q_GLOBAL_STATIC(QThreadStorage<QAtomicInt*>, once_flag)
}
template <class Function>
inline static void qCallOnce(Function func, QBasicAtomicInt& flag)
{
using namespace CallOnce;
#if QT_VERSION < 0x050000
int protectFlag = flag.fetchAndStoreAcquire(flag);
#elif QT_VERSION >= 0x050000
int protectFlag = flag.fetchAndStoreAcquire(flag.load());
#endif
if (protectFlag == CO_Finished)
return;
if (protectFlag == CO_Request && flag.testAndSetRelaxed(protectFlag,
CO_InProgress)) {
func();
flag.fetchAndStoreRelease(CO_Finished);
}
else {
do {
QThread::yieldCurrentThread();
}
while (!flag.testAndSetAcquire(CO_Finished, CO_Finished));
}
}
template <class Function>
inline static void qCallOncePerThread(Function func)
{
using namespace CallOnce;
if (!once_flag()->hasLocalData()) {
once_flag()->setLocalData(new QAtomicInt(CO_Request));
qCallOnce(func, *once_flag()->localData());
}
}
#endif // CALL_ONCE_H
singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
#include <QtGlobal>
#include <QScopedPointer>
#include "call_once.h"
template <class T>
class Singleton
{
private:
typedef T* (*CreateInstanceFunction)();
public:
static T* instance(CreateInstanceFunction create);
private:
static void init();
Singleton();
~Singleton();
Q_DISABLE_COPY(Singleton)
static QBasicAtomicPointer<void> create;
static QBasicAtomicInt flag;
static QBasicAtomicPointer<void> tptr;
bool inited;
};
template <class T>
T* Singleton<T>::instance(CreateInstanceFunction create)
{
Singleton::create.store(create);
qCallOnce(init, flag);
return (T*)tptr.load();
}
template <class T>
void Singleton<T>::init()
{
static Singleton singleton;
if (singleton.inited) {
CreateInstanceFunction createFunction = (CreateInstanceFunction)Singleton::create.load();
tptr.store(createFunction());
}
}
template <class T>
Singleton<T>::Singleton() {
inited = true;
};
template <class T>
Singleton<T>::~Singleton() {
T* createdTptr = (T*)tptr.fetchAndStoreOrdered(nullptr);
if (createdTptr) {
delete createdTptr;
}
create.store(nullptr);
}
template<class T> QBasicAtomicPointer<void> Singleton<T>::create = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
template<class T> QBasicAtomicInt Singleton<T>::flag = Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);
template<class T> QBasicAtomicPointer<void> Singleton<T>::tptr = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
#endif // SINGLETON_H
How to use
// myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
private:
MyClass(QObject* parent = 0);
static MyClass* createInstance();
public:
~MyClass();
static MyClass* instance();
};
#endif // MYCLASS_H
// myclass.cpp
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include "singleton.h"
MyClass::MyClass(QObject* parent):
QObject(parent)
{
}
MyClass* MyClass::createInstance()
{
return new MyClass();
}
MyClass::~MyClass()
{
}
MyClass* MyClass::instance()
{
return Singleton<MyClass>::instance(MyClass::createInstance);
}
#endif // MYCLASS_H
main.cpp
#include <QTextStream>
#include "myclass.h"
#define MyClassInstance Singleton<MyClass>::instance()
int main(int argc, char* argv[])
{
QTextStream(stdout) << MyClass::instance()->metaObject()->className() << endl;
return 0;
}
I think that is will be enough to use next singleton implementation. As I remember, C++11 gurantees that there will be only one instancing/initialization for a static variable.
Original problem was in case, when more than one thread tries to access an instance in same time and there were possible a situation, when singleton was created twice.
template <typename T, typename D = T>
class Singleton
{
friend D;
static_assert(std::is_base_of_v<T, D>, "T should be a base type for D");
public:
static T& instance();
private:
Singleton() = default;
~Singleton() = default;
Singleton( const Singleton& ) = delete;
Singleton& operator=( const Singleton& ) = delete;
};
template <typename T, typename D>
T& Singleton<T, D>::instance()
{
static D inst;
return inst;
}
// Usage:
class MyClass : public Singleton<MyClass>
{
public:
void foo(){}
};
// Access:
MyClass::instance().foo();
Main concept of using Singleton pattern is to restrict the instantiation to certain number of objects, in common use to one.
Q1 : Atomic pointer
Atomic operations are done without interruption , so handled multi-thread instance calls.
Q2 : point of qCallOnce
This function checks if any other threads are executing and if so wait for CO_finished flag in
do {
QThread::yieldCurrentThread();
}
while (!flag.testAndSetAcquire(CO_Finished, CO_Finished));
Q3 : point of qCallOncePerThread
if (!once_flag()->hasLocalData()) {
once_flag()->setLocalData(new QAtomicInt(CO_Request));
I think to handle LocalData of singleton class per each thread instacnes
Related
I have a class MyClass which has a static variable instance. The value of instance is a compile-time constant, but it depends on the complete type MyClass. Is there any way to make instance a constexpr?
// memchunk.hpp
#ifndef MEMCHUNK_HPP
#define MEMCHUNK_HPP
#include <new>
#include <utility>
enum class DestroyOption {
Implicit,
Explicit,
};
// a wrapper for placement new
template <class T, DestroyOption Opt = DestroyOption::Implicit> class MemChunk {
alignas(T) char buf[sizeof(T)];
public:
template <typename... Args> void construct(Args &&...args) {
new (buf) T(std::forward<Args>(args)...);
}
void destroy() { get()->~T(); }
constexpr T *get() { return reinterpret_cast<T *>(buf); }
~MemChunk() {
if constexpr (Opt == DestroyOption::Implicit)
destroy();
}
};
#endif // MEMCHUNK_HPP
// myclass.cpp
#include "memchunk.hpp"
// struct MyClass; // forward declaration
// MemChunk<MyClass> obj; // error: incomplete type MyClass
class MyClass {
static const MyClass *instance; // better to be constexpr
};
MemChunk<MyClass> obj;
const MyClass *MyClass::instance = obj.get();
Use a function instead:
class MyClass {
static constexpr MyClass* instance();
};
MemChunk<MyClass> obj;
constexpr MyClass* MyClass::instance() {
return obj.get();
}
However, this is pointless because obj.get() cannot be used in a constexpr context (because of the reinterpret_cast, as mentioned in the comments).
Demo
I'm implementing a Singleton template in C++. I try to achieve thread-safe by std::call_once and std::once_flag, but somehow link error happens.
singleton.h
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <boost/noncopyable.hpp>
#include <mutex>
template<typename T>
class Singleton : boost::noncopyable {
public:
Singleton() = delete;
static T& getInstance() {
std::call_once(init_flag_, &Singleton::init);
return *val_;
}
private:
static void init() {
val_ = new T();
}
private:
static std::once_flag init_flag_;
static T* val_;
};
#endif // _SINGLETON_H_
test_singleton.cc
#include "singleton.h"
#include <iostream>
class Log {
public:
void log() {
std::cout << "log" << std::endl;
}
};
int main() {
Log & logger = Singleton<Log>::getInstance();
logger.log();
}
And my g++ statement is
g++ -std=c++14 -pthread -o test test_singleton.cc
Error message:
/tmp/ccoxQBXl.o: In function `Singleton<Log>::getInstance()':
test_singleton.cc:(.text._ZN9SingletonI3LogE11getInstanceEv[_ZN9SingletonI3LogE11getInstanceEv]+0x2c): undefined reference to `Singleton<Log>::init_flag_'
test_singleton.cc:(.text._ZN9SingletonI3LogE11getInstanceEv[_ZN9SingletonI3LogE11getInstanceEv]+0x38): undefined reference to `Singleton<Log>::val_'
/tmp/ccoxQBXl.o: In function `Singleton<Log>::init()':
test_singleton.cc:(.text._ZN9SingletonI3LogE4initEv[_ZN9SingletonI3LogE4initEv]+0x11): undefined reference to `Singleton<Log>::val_'
collect2: error: ld returned 1 exit status
Finally got it. The only problem is I didn't initialize the static variables.
For C++17, inline keyword allows initialization within class.
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include <boost/noncopyable.hpp>
#include <mutex>
template<typename T>
class Singleton : boost::noncopyable {
public:
Singleton() = delete;
static T& getInstance() {
std::call_once(init_flag_, &Singleton::init);
return *val_;
}
private:
static void init() {
val_ = new T();
}
private:
static inline std::once_flag init_flag_{};
static inline T* val_ = nullptr;
};
#endif // SINGLETON_H_
I can't seem to figure out how to write the includes of the Visitor Pattern with this simple example. No matter what I do I always end up with circular dependencies, but no other way makes sense.
Also I apologize for the different header guards (pragma vs. #ifndef), I was testing #pragma out and hadn't updated the files yet.
Client.cpp
#include "OneVisitor.h"
#include "DataStructure.h"
int main (int argc, char * argv [])
{
OneVisitor v;
DataStructure d;
}
DataStructure.h
#ifndef _DATA_STRUCTURE_H_
#define _DATA_STRUCTURE_H_
#include "ElementA.h"
class DataStructure {
public:
DataStructure (Visitor & v)
{
std::cout << "ACCEPTS";
a->accept(v);
};
private:
ElementA * a;
};
#endif
Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
#include "Visitor.h"
#include <iostream>
class Element {
public:
virtual void accept (Visitor & v) = 0;
void talk ()
{
std::cout << "ELEMENT TALKING";
};
};
#endif
ElementA.h
#pragma once
#include "Element.h"
#include "Visitor.h"
class ElementA : public Element {
public:
virtual void accept (Visitor & v) override
{
v.Visit(*this);
};
void talk ()
{
std::cout << "ELEMENT A TALKING";
};
};
Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
#include "ElementA.h"
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif
OneVisitor.h
#ifndef _ONE_VISITOR_H_
#define _ONE_VISITOR_H_
#include "Visitor.h"
class OneVisitor : public Visitor {
public:
virtual void Visit (ElementA & a) override
{
a.talk();
};
};
#endif
When I run this, I get the error "Visitor has not been declared" in Element.h, ElementA.h, ElementB.h. How can i get Visitor defined in these classes without causing circular dependencies?
A visitor is a very abstract concept, and it makes sense to template it in this case. Using templates allows us to get rid of circular dependencies, and simplify things considerably.
// Visitor.hpp
#pragma once
template<class T>
class Visitor {
public:
virtual void visit(T& item) = 0;
virtual ~Visitor() = default;
};
Now, if you want to have visitor for Element, you could just use Visitor<Element>:
// Element.hpp
#pragma once
#include "Visitor.hpp"
#include <iostream>
class Element
{
public:
virtual void accept(Visitor<Element>& v)
{
v.visit(*this);
}
virtual void talk() {
std::cout << "Element talking!\n";
}
virtual ~Element() = default;
};
Now that we have these things, we can also write a function to convert lambdas into visitors:
template<class T, class Func>
struct FunctionVisitor : public Visitor<T> {
Func func;
FunctionVisitor() = default;
FunctionVisitor(FunctionVisitor const&) = default;
FunctionVisitor(FunctionVisitor&&) = default;
FunctionVisitor(Func const& func)
: func(func)
{
}
void visit(T& item) override {
func(item);
}
};
template<class T, class Func>
FunctionVisitor<T, Func> makeVisitor(Func const& f) {
return FunctionVisitor<T, Func>(f);
}
Bringing it all together
This allows us to write nice code like this:
#include "Element.hpp"
#include "Visitor.hpp"
#include <vector>
class ElemA : public Element {
public:
void talk() override {
std::cout << "ElemA talking!\n";
}
};
class ElemB : public Element {
public:
void talk() override {
std::cout << "ElemB talking!\n";
}
};
class ElemC : public Element {
public:
void talk() override {
std::cout << "ElemC talking!\n";
}
};
void visitAll(std::vector<Element*>& elements, Visitor<Element>& visitor) {
for(auto e : elements) {
e.accept(visitor);
}
}
int main() {
std::vector<Element*> elements {
new ElemA(),
new ElemB(),
new ElemC()
};
auto talk = [](Element& e) { e.talk(); };
visitAll(elements, makeVisitor<Element>(talk));
}
By using a forward declaration of the class ElementA; in Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
// Just use a forward declaration of the class ElementA;
// NOTE1: The include of ElementA.h is not needed anymore.
// NOTE2: The visitor.h doesn't need to know what is defined
// in ElementA, only your .cpp needs, this is how forward
// declaration works.
class ElementA;
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif
There is an issue with my Instance class in that I noticed a difference in behavior that stems from two methods of initializing a static member.
The class template Instance is keeping track of a unique count. The unique count is being used to keep track of the amount of derived classes for a specific type. It is also used to assign a unique id/index for derived classes.
The first is initialized as follows:
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_static_assign{ std::numeric_limits<Key>::min() };
The second is initialized as such:
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_default{ 0 };
Program's output
1 1
2 1
I expect the two values to be equal because they should both be incrementing. However count_static_assign, is giving the wrong output as it appears to reset and be equal to 1 twice. Thus, I would like to know why there is a difference in behavior between these two static variables.
Here are the files for the program that demonstrates the error.
Instance.h
#ifndef INSTANCE_H
#define INSTANCE_H
#include <cinttypes>
#include <limits>
#include <iostream>
template<typename Derived, typename Key = std::uint16_t>
class Instance {
public:
using KeyType = Key;
static KeyType count_static_assign;
static KeyType count_default;
public:
Instance() = default;
virtual ~Instance() = default;
virtual KeyType getInstance() const = 0;
protected:
static KeyType generate() {
count_static_assign++;
count_default++;
std::cout << count_default << ' ' << count_static_assign << '\n';
return count_default;
}
};
//doesn't behave as expected
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_static_assign{ std::numeric_limits<Key>::min() };
//behaves as expected
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_default{ 0 };
#endif
Base.h
#ifndef BASE_H
#define BASE_H
#include <cinttypes>
#include <typeindex>
#include <memory>
#include "Instance.h"
class Base : public Instance<Base>
{
public:
Base(){}
~Base(){}
};
template<typename Derived>
class CRTPBase : public Base {
public:
static const KeyType STATIC_TYPE;
CRTPBase() {}
virtual ~CRTPBase() {}
virtual KeyType getInstance() const override {
return STATIC_TYPE;
}
};
template<typename Derived>
const typename CRTPBase<Derived>::KeyType CRTPBase<Derived>::STATIC_TYPE = CRTPBase<Derived>::generate();
#endif
Foo.h
#ifndef FOO_H
#define FOO_H
#include "Base.h"
struct Foo : public CRTPBase<Foo> {
Foo();
~Foo();
};
#endif
Foo.cpp
#include "Foo.h"
Foo::Foo()
{
}
Foo::~Foo()
{
}
Bar.h
#ifndef BAR_H
#define BAR_H
#include "Base.h"
struct Bar : public CRTPBase<Bar>
{
public:
Bar();
~Bar();
};
#endif
Bar.cpp
#include "Bar.h"
Bar::Bar()
{
}
Bar::~Bar()
{
}
main.cpp
#include "Foo.h"
#include "Bar.h"
int main() {
Foo foo;
Bar bar;
std::cin.get();
}
If it matters, I am using Visual Studio 2017(Full Version-191426433) to compile. In addition, debug and release mode make no difference.
This code looks correct to me: count_default and count_static_assign have constant expressions as initializers, so they must be initialized before any dynamic initialization happens. STATIC_TYPE is dynamic initialization.
OP reports that changing std::numeric_limits<Key>::min() to 0 fixes the behaviour of the program, so I would conjecture that the compiler has a bug that it does not consider the constexpr function std::numeric_limits<Key>::min() to be a constant expression.
To work around this you could try some other way of coming up with a constant initializer for count_static_assign, e.g. a constexpr function that you write yourself, or a specialization for each type that you do use.
When I run the following code and press the enter button, I get a Segmentation Fault.
I've searched everywhere on the internet, but I can't find the problem. I'm quite new to C++/Qt.
The base class:
stack.h
#ifndef STACK_H
#define STACK_H
template <class T> class stack
{
public:
stack();
virtual T pop() = 0;
virtual void push(T i) = 0;
};
#endif // STACK_H
stack.cpp
#include "stack.h"
template<class T> stack<T>::stack()
{
}
arraystack.h
#ifndef ARRAYSTACK_H
#define ARRAYSTACK_H
#include "stack.h"
template <class T> class arraystack : public stack<T>
{
public:
arraystack();
T pop();
void push(T i);
};
#endif // ARRAYSTACK_H
arraystack.cpp
#include "arraystack.h"
#include <QDebug>
template<class T> arraystack<T>::arraystack()
{
}
template<class T> T arraystack<T>::pop(){
qDebug() << "popping bad";
}
template<class T> void arraystack<T>::push(T i){
qDebug() << "pushing shit";
}
The part that calls the pop-Function:
calculator.h
// ...
private:
Ui::calculator *ui;
arraystack<int> *h;
bool integer;
// ...
calculator.cpp
// ...
void calculator::on_b_enter_clicked()
{
h->pop();
}
// ...
Error:
The inferior stopped because it received a signal from the Operating System
Signal name: SIGSEGV
Signal meaning: Segmentation Fault
This code:
A.h
template <typename T>
class A
{
public:
A(){}
virtual void f1() = 0;
};
template <typename T>
class B: public A<T>
{
public:
B(){}
void f1(){}
};
main.cpp
#include "A.h"
int main ()
{
A<int> *a = new B<int>();
a->f1();
}
Compiles and works, because all template functions are defined in header file. If you want to split the declaration and the definition, you can use one of these methods:
Include the cpp file at the bottom of your header file
Include the cpp file in main.cpp