I was brushing up my C++ knowledge and I chose implementing singleton to be starting point. Just I didn't want to implement the classic private constructor & static getInstance method way of doing it.
So here is a Rube Goldberg way,
class Singleton : public IDestroy {
static Singleton* iS; // Singleton instance
static int count; // number of undeleted objects
int a;
public:
Singleton(int A = 0) {
if (!iS) {
a = A;
iS = this;
}
count++;
}
void destroy() {delete this;} // way to destroy HeapOnly
int get() {
return a;
}
static void* operator new(std::size_t size);
static void operator delete(void* ptr);
protected:
// Ensuring construction of HeapOnly objects
// If object created on stack, there is no control of new operator
~Singleton() {
count--;
std::cout << "Destroyed, remaining :" << count << std::endl;
}
};
void* Singleton::operator new(std::size_t size)
{
if (iS)
return iS;
else
return ::operator new(size);
}
void Singleton::operator delete(void* ptr)
{
if (!count)
{
::operator delete(ptr);
iS = 0;
std::cout << "Cleared memory" << std::endl;
}
}
Singleton* Singleton::iS = 0;
int Singleton::count = 0;
And to work well with shared_ptr:
class IDestroy
{
public:
virtual void destroy() = 0;
};
class HeapOnlyDestroyer {
public:
void operator()(IDestroy* s) {
s->destroy();
}
};
Now, I can use the same object like:
a = new Singleton(1);
..
a->destroy();
or
shared_ptr<Singleton> s(new Singleton(1), HeapOnlyDestroyer());
I wanted to know if there are any problems in this approach, also its pros/cons over the classic way of using static getInstance method.
Cons:
It is confusing that object is not actually being created with new
Inheritance is possible that will create mess to maintain singleton functionality (could this be turned into a feature?)
First of all, what is the pro of this implementation?
Just I didn't want to implement the classic private constructor[...]
Why not?
Why not following the least surprise rule and using the Meyers Singleton?
e.g:
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/4/
class Log {
public:
static Log& Instance() {
static Log theLog;
return theLog;
}
void Write(char const *logline);
bool SaveTo(char const *filename);
private:
Log(); // ctor is hidden
Log(Log const&); // copy ctor is hidden
Log& operator=(Log const&); // assign op is hidden
static std::list<std::string> m_data;
};
P.S.: Off the records, my first implementation of "singleton" was like this. After explaining the code to a college for half an hour, suddenly he asked: "Is it a singleton what you are trying to achieve?" I had to confess, I had no idea at that time, what a singleton was.
Related
I want to write an generic object pool class and the object pool should be singleton, it is easy to access that object pool everywhere.
template <class T>
class Pool
{
T* _freeObjs;
public:
Pool<T>& getInstance()
{
static Pool<T> instance;
return instance;
}
T* acquire() { ... }
void release(T* obj) { ... }
private:
Pool()
{
_freeObjs = (T*)malloc(sizeof(T) * 100);
}
};
class Foo
{
int i;
public:
void* operator new(size_t size)
{
void * p = Pool<Foo>::getInstance().acquire();
return p;
}
void operator delete(void * p)
{
Pool<Foo>::getInstance().release(p);
}
};
int main()
{
{
Foo* f = new Foo();
delete f;
}
return 0;
}
but the compiler show the following error message,
error: cannot call member function ‘Pool& Pool::getInstance() [with T = Foo]’ without object
void * p = Pool::getInstance().acquire();
Update: thanks, PaulMcKenzie
After i add static to getInstance() function, the code is work.
Now, i move the overload operator new/delete to base class, if any wrong with my following code ?
class PooledObject
{
public:
void* operator new(size_t size)
{
void * p = Pool<PooledObject>::getInstance().acquire();
return p;
}
void operator delete(void * p)
{
Pool<PooledObject>::getInstance().release((PooledObject*)p);
}
};
class Foo : public PooledObject
{
int i;
public:
};
Your Pool<T>& getInstance() is not static. It needs to be a static function if you want to access getInstance without an object being created:
static Pool<T>& getInstance()
{
static Pool<T> instance;
return instance;
}
See code below for the details, but the underlying scenario is as follows. I have a container (a session) that I can place objects in and pull out from.
Similar to:
std::shared_ptr<Tiger> t = ...;
session.store("tigers/1", t);
std::shared_ptr<Tiger> t2 = session.load<Tiger>("tigers/1");
With both functions defined as:
class Session {
template<class T>
void store(std::string id, std::shared_ptr<T> instance);
template<class T>
std::shared_ptr<T> load(std::string id);
}
Note that a session can store heterogeneous types, but at store and load time I statically known what the type of the variable is.
My problem is that I run into a situation where the user wants to put a Tiger into the session but checks out a base type, instead. For example:
session.load<Animal>("tigers/1");
Right now, I'm effectively storing the data as void* inside the session and use reinterpret_cast to get them back to the user provided type. This... works, as long as everything is trivial, but when we get to a slightly more complex situation, we run into issues.
Here is the full code demonstrating my issue:
struct Animal
{
virtual void Pet() const = 0;
};
struct IJumpable
{
virtual void Jump() const = 0;
};
struct Tiger : Animal, IJumpable
{
void Pet() const override
{
std::cout << "Pet\n";
}
void Jump() const override
{
std::cout << "Jump\n";
}
};
int main()
{
auto cat = std::make_shared<Tiger>();
// how the data is stored inside the session
auto any_ptr = std::static_pointer_cast<void>(cat);
// how we get the data out of the session
auto namable = std::static_pointer_cast<IJumpable>(any_ptr);
namable->Jump();
std::cout << std::endl;
}
If you run this code, you'll see that it runs, but instead of calling Jump, it calls to Pet. I understand that this is because of the wrong virtual method table being used, since I'm effectively calling reinterpret_cast on `void*.
My question is if there is a good way to handle this scenario in C++. I've looked around and didn't see anything that matches what I need.
Everything I found about heterogeneous containers always assumed a shared base class, which I don't have nor want. Is this possible?
You could make the user provide you with the correct casting trek to follow:
class Session {
template<class T>
void store(std::string id, std::shared_ptr<T> instance);
template<class T>
std::shared_ptr<T> load(std::string id);
template<class Stored, class Retrieved>
std::shared_ptr<Retrieved> load_as(std::string id) {
auto stored = load<Stored>(id);
return std::static_pointer_cast<Retrieved>(stored);
}
}
This makes a messy usage at the caller site, but the information must come from somewhere:
auto shere_khan = make_shared<Tiger>();
session.store("tigers/1", shere_khan);
auto bagheera = session.load_as<Tiger, IJumpable>("tigers/1");
Solution courtesy of my brother who happens to be a C++ expert with no stackoverflow :)
Here is a void_ptr implementation that enables polymorphic casting using exception handling to discover types. The performance should be close to that of a dynamic_cast. You should be able to optimize the above using std::type_index and caching the offsets.
#include <stdio.h>
class void_ptr {
void* obj;
void (*discover_type)(void*);
template<typename T>
static void throw_typed_object(void* obj)
{
T* t = static_cast<T*>(obj);
throw t;
}
public:
void_ptr() : obj(0) {}
template<typename T>
void_ptr(T* t) : obj(t), discover_type(throw_typed_object<T>)
{
}
template<typename T>
T* cast() const
{
try {
discover_type(obj);
} catch(T* t) {
return t;
} catch(...) {
}
return 0;
}
};
struct Animal {
virtual ~Animal() {}
virtual const char* name() { return "Animal"; }
};
struct Speaker {
virtual ~Speaker() {}
virtual const char* speak() { return "hello"; }
};
struct Lion : public Animal, public Speaker {
virtual const char* name() { return "Lion"; }
virtual const char* speak() { return "Roar"; }
};
int main()
{
void_ptr ptr(new Lion());
Animal* a = ptr.cast<Animal>();
Speaker* s = ptr.cast<Speaker>();
printf("%s\n", a->name());
printf("%s\n", s->speak());
}
IMO best solution is not to cast to pointer to void but to other type which can be dynamic sidecast to required type.
#include <iostream>
#include <memory>
struct Animal
{
virtual ~Animal() {}
virtual void Pet() const = 0;
};
struct IJumpable
{
virtual ~IJumpable() {}
virtual void Jump() const = 0;
};
struct IStrorable
{
virtual ~IStrorable() {}
};
struct Tiger : Animal, IJumpable, IStrorable
{
void Pet() const override
{
std::cout << "Pet\n";
}
void Jump() const override
{
std::cout << "Jump\n";
}
};
int main()
{
auto cat = std::make_shared<Tiger>();
auto any_ptr = std::static_pointer_cast<IStrorable>(cat);
auto namable = std::dynamic_pointer_cast<IJumpable>(any_ptr);
namable->Jump();
std::cout << std::endl;
}
Live example
Other solutions require use of std::any, but this will be less handy.
It is a bit disturbing that your method load is a template.
I want to put a limit on the number of instances you can make of a class.
I have the following code:
class A {
static int cnt;
int x;
public:
A() {
cout<<"ctor called\n";
}
void* operator new(size_t size_in) {
if(cnt<=10) {
void *p=malloc(size_in);
if(p==NULL) {
throw bad_alloc();
} else {
cout<<"Memory allocation successful\n";
++cnt;
return p;
}
} else {
throw bad_alloc();
}
}
~A() {
cout<<"Cleaning up the mess\n";
}
};
int A::cnt=0;
int main() {
A *a[20];
for(int i=0;i<20;++i) {
try {
a[i]=new A();
} catch (bad_alloc &e) {
cout<<"Error in allocating memory\n";
}
}
try {
A b;
} catch (bad_alloc &e) {
cout<<"Error in allocating memory on stack\n";
}
return 0;
}
Using a static counter and overloading the new operator I am able to put a limit on the number of objects that can be created on Heap. I want to limit the number of instances created on Stack also. One way is to make constructor private and provide a public API which first checks the counter and then returns accordingly.
Is there any other way of doing this?
Is there any other way of doing this??
You may just increase and check the counter in the constructor, the object will be destroyed if you throw an exception out of it. Furthermore, you won't have to distinguish between stack and heap.
The best way to do it is to create helper template class and count objects using constructor and destructor:
class instance_limit_reached : public std::logic_error
{
public:
using logic_error::logic_error;
};
template<typename T, int MaxInst>
class LimitInstances
{
static std::atomic<int> instanceCount;
void onNewInstance() {
chekcTheLimit();
++instanceCount;
}
void chekcTheLimit() {
if (instanceCount >= MaxInst)
throw instance_limit_reached(std::string("Limit reached for ") + typeid(T).name());
}
public:
~LimitInstances() {
--instanceCount;
}
LimitInstances() {
onNewInstance();
}
LimitInstances(const LimitInstances<T, MaxInst> &) {
onNewInstance();
}
LimitInstances(LimitInstances<T, MaxInst> &&) {
onNewInstance();
}
};
Live example with field use or example with CRTP
Now there is one important question, when object is moved do you consider this as a new instance (my example) or old instance (my code needs tweaking)?
For fun, this is how I would do it: a CRTP design to be reusable with thread safe code:
template<class ToLimit,size_t MaxInstances>
class InstanceLimiter{
static inline std::atomic<int> instances=0;
private:
static increase_count(){
//memory order relaxed is sufficient because there is
//only one modification order for each atomic objects.
int actual=instances.load(std::memory_order_relaxed);
do{
if (actual>=MaxInstances) throw some_error{};
} while (instances.compare_exchange_weak(actual,actual+1,
std::memory_order_relaxed,std::memory_order_relaxed));
}
protected:
//Provide definition for default constructor, copy constructor
// and copy assignment operator so that defaulted derived special
// member function behave as expected.
InstanceLimiter(){increase_count();}
InstanceLimiter(const InstanceLimiter&){increase_count();}
InstanceLimiter& operator=(const InstanceLimiter&){
increase_count();
return *this;
}
~InstanceLimiter(){
instances.fetch_add(-1,std::memory_order_relaxed);
}
};
class A: InstanceLimiter<A,10> {
int x;
public:
A() {
//InstanceLimiter default constructor implicitly called
cout<<"ctor called\n";
}
A(int x)
//InstanceLimiter default constructor implicitly called here
:x{x}{}
//Implicitly declarer move/copy constructor/assignement implicitly calls
// the copy constructor/assignment of InstanceLimiter
~A() {
cout<<"Cleaning up the mess\n";
//Default destructor of InstanceLimiter implicitly called here.
}
};
Last but not least: if you plan to use it in real code, consider to make your class A noexcept default and move constructible by providing it a default state that does not count as an instance.
I want to limit the number of instances created on Stack also
If you want different limits for Heap and Stack object, it seem to me that the cleaner way is the one of the private constructor with friend make functions (one for heap objects and one for stack object) with counters inside the make functions.
I mean... you can write A as follows
class A
{
private:
int x;
A (int x0 = 0)
{ std::cout << "ctor called" << std::endl; }
public:
~A()
{ std::cout << "cleaning up the mess" << std::endl; }
friend A * makeAinHeap (int);
friend A makeAinStack (int);
};
and the make-in-heap function is simply
A * makeAinHeap (int x)
{
constexpr auto maxAH { 3u };
static auto ah { 0u };
if ( ++ah > maxAH )
throw std::runtime_error("no more A in Heap");
return new A{x};
}
and the analogous make-in-stack function is
A makeAinStack (int x)
{
constexpr auto maxAS { 2u };
static auto as { 0u };
if ( ++as > maxAS )
throw std::runtime_error("no more A in Stack");
return A{x};
}
You can check all with the following main()
int main ()
{
auto p1 { makeAinHeap(0) }; // OK
auto p2 { makeAinHeap(0) }; // OK
auto p3 { makeAinHeap(0) }; // OK
//auto p4 { makeAinHeap(0) }; // throw an exception
auto s1 { makeAinStack(0) }; // OK
auto s2 { makeAinStack(0) }; // OK
//auto s3 { makeAinStack(0) }; // throw an exception
delete p1;
delete p2;
delete p3;
}
I am learning about the singleton design pattern with Chapter 29 of Professional C++, Second Edition1.
It illustrates a singleton implementation of a Logger class that covers thread-safety requirements:
Header
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <mutex>
// Definition of a multithread safe singleton logger class
class Logger
{
public:
static const std::string kLogLevelDebug;
static const std::string kLogLevelInfo;
static const std::string kLogLevelError;
// Returns a reference to the singleton Logger object
static Logger& instance();
// Logs a single message at the given log level
void log(const std::string& inMessage,
const std::string& inLogLevel);
// Logs a vector of messages at the given log level
void log(const std::vector<std::string>& inMessages,
const std::string& inLogLevel);
protected:
// Static variable for the one-and-only instance
static Logger* pInstance;
// Constant for the filename
static const char* const kLogFileName;
// Data member for the output stream
std::ofstream mOutputStream;
// Embedded class to make sure the single Logger
// instance gets deleted on program shutdown.
friend class Cleanup;
class Cleanup
{
public:
~Cleanup();
};
// Logs message. The thread should own a lock on sMutex
// before calling this function.
void logHelper(const std::string& inMessage,
const std::string& inLogLevel);
private:
Logger();
virtual ~Logger();
Logger(const Logger&);
Logger& operator=(const Logger&);
static std::mutex sMutex;
};
Implementation
#include <stdexcept>
#include "Logger.h"
using namespace std;
const string Logger::kLogLevelDebug = "DEBUG";
const string Logger::kLogLevelInfo = "INFO";
const string Logger::kLogLevelError = "ERROR";
const char* const Logger::kLogFileName = "log.out";
Logger* Logger::pInstance = nullptr;
mutex Logger::sMutex;
Logger& Logger::instance()
{
static Cleanup cleanup;
lock_guard<mutex> guard(sMutex);
if (pInstance == nullptr)
pInstance = new Logger();
return *pInstance;
}
Logger::Cleanup::~Cleanup()
{
lock_guard<mutex> guard(Logger::sMutex);
delete Logger::pInstance;
Logger::pInstance = nullptr;
}
Logger::~Logger()
{
mOutputStream.close();
}
Logger::Logger()
{
mOutputStream.open(kLogFileName, ios_base::app);
if (!mOutputStream.good()) {
throw runtime_error("Unable to initialize the Logger!");
}
}
void Logger::log(const string& inMessage, const string& inLogLevel)
{
lock_guard<mutex> guard(sMutex);
logHelper(inMessage, inLogLevel);
}
void Logger::log(const vector<string>& inMessages, const string& inLogLevel)
{
lock_guard<mutex> guard(sMutex);
for (size_t i = 0; i < inMessages.size(); i++) {
logHelper(inMessages[i], inLogLevel);
}
}
void Logger::logHelper(const std::string& inMessage,
const std::string& inLogLevel)
{
mOutputStream << inLogLevel << ": " << inMessage << endl;
}
It goes on to explain why the friend class Cleanup is introduced:
The Cleanup class is there to make sure the single Logger instance
gets deleted properly on program shutdown. This is necessary because
this implementation is dynamically allocating the Logger instance by
using the new operator in a block of code protected with a mutex. A
static instance of the Cleanup class will be created the first time
the instance() method is called. When the program terminates, the C++
runtime will destroy this static Cleanup instance, which will trigger
the deletion of the Logger object and a call to the Logger destructor
to close the file.
I find it very confusing that it states "This is necessary because...", as if there were no other alternative.
My questions:
1) Is it really necessary? Wouldn't it be enough to just have all the handling in the destructor?, like:
Logger::~Logger()
{
{
lock_guard<mutex> guard(Logger::sMutex);
delete Logger::pInstance;
Logger::pInstance = nullptr;
}
mOutputStream.close();
}
2) If the answer to 1) is "yes, it is indeed necessary!", I would like to know why.
1Professional C++, Second Edition by Marc Gregoire , Nicholas A. Solter , Scott J. Kleper Publisher: Wrox Published: October 2011
Yes, this is needed in this case. Since the book used new and handed out a pointer there is no object that will go out of scope that will cause the destructor to fire. The only way to do so is to call delete somewhere on that pointer. Instead of requiring you to do that the Cleanup class was created to do that.
All of this though can be avoided if you use a Meyers Singleton. That uses a static variable of the singleton type and returns a pointer/reference to that. That will automatically be destroyed at the end of the program unlike the book version. A Meyers Singleton looks like:
class Singleton {
public:
static Singleton* Instance() { static Singleton s; return &s; }
Singleton(const Singleton&) = delete;
void operator=(const Singleton&) = delete;
private:
Singleton() = default;
};
Let me preference that I mostly develop in C# and the C++ development which I have done did not fully leverage the C++ language. I am now trying to use the language as it was intended and I am pulling my hair out with const declarations in passed arguments. In the past I never used them or hacked my way into making them work with the STL.
My understanding that I would create the following function when I want to use o as readonly in the function:
void foo(const MyClass* o);
So here is my problem...code first:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
In main() the compiler (g++ version 4.7.2) balks in doSomethingB:
doSomethingA(o->child());
with error: passing 'const ClassB' as 'this' argument of 'ClassA* ClassB::child()' discards qualifiers [-fpermissive]
Now I am passing my classes to functions as pointers. I plan on always using pointers because I have a problem with the reference/pointer options. I'm choosing one, pointers, and sticking with it. So doSomethingA and doSomethingB I want that to be const to tell the programmer that their class is not being altered. But I only want one version of child() which I want to use sometimes as "read only" and other times allow the user to change the data within the child object (not the best method, I grant that, but there are some use cases where I need this). I even tried:
doSomethingA(const_cast<const ClassA*>(o->child()));
But that did not work.
In the past I removed the const declarations in the functions to make something like this work but now I want to use proper c++. Help please.
try
ClassA* child() const { return &m_child; }
or
const ClassA* child() const { return &m_child; }
to keep the const correctness
Also, you don't need to use pointers as long as you don't plan passing nullptr. So you can do the following:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
References still alow polymorphic stuff same way as pointers.
You're attempting to access a non-const function against a const object. You need to make the function const :
const ClassA* child() const { return &m_child; }
You can also provide a const and non-const version:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
This way you can call non-const methods on ClassA when you have a non-const object.