Functional vs Safety / Static vs Dynamic instantiations - c++

I'm in a situation where I think that two implementations are correct, and I don't know which one to choose.
I've an application simulating card readers. It has a GUI where you choose which serial port, and speed to use, and a play and stop button.
I'm looking for the best implementation for reader construction.
I have a SimulatorCore class who's living as long as my application
SimulatorCore instantiate the Reader class. And it will be possible to simulate multiple readers on multiple serial port.
Two possibilities:
My Reader is a pointer (dynamic instantiation), I instantiate it when play button is hit, delete it when stop button is hit.
My Reader is an object (static instantiation), I instantiate it in SimulatorCore constructor then create and call Reader.init() and Reader.cleanup() into my Reader class and call these when play and stop are being hit
I personally see the functional side, and I clearly want to use pointer, and do not have any reader instantiate if no reader are simulated.
Someone say me that I should use static instantiation (Reason : for safety, and because "it's bad to use pointer when you have choice to not use them")
I'm not familiar with them, but I think I can also use smart pointer.
Code samples: 1st solution:
class SimulatorCore
{
play(){reader = new Reader();};
stop(){delete reader; reader = nullptr;};
private:
Reader *reader;
}
Code samples: 2nd solution:
class SimulatorCore
{
play(){reader.init();};
stop(){reader.cleanup();};
private:
Reader reader;
}
The code is unstest, I've juste wite it for illustration.
What is the best solution? Why?

You can easily use shared_ptr/unique_ptr:
class SimulatorCore
{
play(){_reader = make_shared<Reader>();};
stop(){_reader = nullptr};
private:
shared_ptr<Reader> _reader;
}
That will solve your problem right way, I guess.
Dynamic allocation gives some problems, for example, with throwing exception (there can be memory losing if between play() and stop() there will be thrown exception, for example, and stop() will never be called). Or you can just forget somewhere call stop() before destruction of SimulatorCore, it is possible if program is heavy.
If you never tried smart pointers, it is good chance to start doing it.

You should generally avoid performing dynamic allocation with new yourself, so if you were going to go with the 1st solution, you should use smart pointers instead.
However, the main question here is a question of logic. A real card reader exists in an idle state until it is being used. In the 2nd solution, what do init and cleanup do? Do they simply setup the card reader into an idle state or do they start simulating actually having a card being read? If it's the first case, I suggest that this behaviour should be in the constructor and destructor of Reader, and then creating a Reader object denotes bringing a card reader into existence. If it's the second case, then I'd say the 2nd solution is pretty much correct, just that the functions are badly named.
What seems most logical to me is something more like this:
class SimulatorCore
{
play(){reader.start();};
stop(){reader.stop();};
private:
Reader reader;
}
Yes, all I've done is change the function names for Reader. However, the functions now are not responsible for initialising or cleaning up the reader - that responsibility is in the hands of Reader's constructor and destructor. Instead, start and stop begin and end simulation of the Reader. A single Reader instance can then enter and exit this simulation mode multiple times in its lifetime.
If you later want to extend this idea to multiple Readers, you can just change the member to:
std::vector<Reader> readers;
However, I cannot know for certain that this is what you want because I don't know the logic of your program. Hopefully this will give you some ideas though.
Again, whatever you decide to do, you should avoid using new to allocate your Readers and then also avoid using raw pointers to refer to those Readers. Use smart pointers and their corresponding make_... functions to dynamically allocate those objects.

It clearly depends on how your whole program is organized, but in general, I think I would prefer the static approach, because of responsability considerations:
Suppose you have a separate class that handles serial communication. That class will send and receive messages and dispatch them to the reader class. A message may arrive at any time. The difference of the dynamic and static approaches is:
With the dynamic approach, the serial class must test if the reader actually exists before dispatching a message. Or the reader has to register and unregister itself in the serial class.
With the static approach, the reader class can decide for itself, if it is able to process the message at the moment, or not.
So I think the static approach is a bit easier and straight-forward.
However, if there is a chance that you will have to implement other, different reader classes in the future, the dynamic approach will make this extension easier, because the appropriate class can easily be instanciated at runtime.
So the dynamic approach offers more flexibility.

Related

How to expose a thread-safe interface that allocate resources?

I'm trying to expose a C interface for my C++ library. This notably involve functions that allow the user to create, launch, query the status, then release a background task.
The task is implemented within a C++ class, which members are protected from concurrent read/write via an std::mutex.
My issue comes when I expose a C interface for this background task. Basically I have say the following functions (assuming task_t is an opaque pointer to an actual struct containing the real task class):
task_t* mylib_task_create();
bool mylib_task_is_running(task_t* task);
void mylib_task_release(task_t* task);
My goal is to make any concurrent usage of these functions thread-safe, however I'm not sure exactly how, i.e. that if a client code thread calls mylib_task_is_running() at the same time that another thread calls mylib_task_release(), then everything's fine.
At first I thought about adding an std::mutex to the implementation of task_t, but that means the delete statement at the end of mylib_task_release() will have to happen while the mutex is not held, which means it doesn't completely solve the problem.
I also thought about using some sort of reference counting but I still end up against the same kind of issue where the actual delete might happen right after a hypothetical retain() function is called.
I feel like there should be a (relatively) simple solution to this but I can't quite put my hand on it. How can I make it so I don't have to force the client code to protect accesses to task_t?
if task_t is being deleted, you should ensure that nobody else has a pointer to it.
if one thread is deleting task_t and the other is trying to acquire it's mutex, it should be apparent that you should not have deleted the task_t.
shared_ptrs are a great help for this.

shared_ptr Real life use-cases

shared_ptr is to be used when we have a scenario where it is desirable to have multiple owners of a dynamically allocated item.
Problem is, I can't imagine any scenario where we require multiple owners. Every use-case I can image can be solved with a unique_ptr.
Could someone provide a real life use-case example with code where shared_ptr is required (and by required, I mean the optimal choice as a smart pointer)? And by "real life" I mean some practical and pragmatic use-case, not something overly abstract and fictitious.
In our simulator product, we use a framework to deliver messages between simulation components (called endpoints). These endpoints could reside on multiple threads within a process, or even on multiple machines in a simulation cluster with messages routed through a mesh of RDMA or TCP connections. The API looks roughly like:
class Endpoint {
public:
// Fill in sender address, etc., in msg, then send it to all
// subscribers on topic.
void send(std::unique_ptr<Message> msg, TopicId topic);
// Register this endpoint as a subscriber to topic, with handler
// called on receiving messages on that topic.
void subscribe(TopicId topic,
std::function<void(std::shared_ptr<const Message>)> handler);
};
In general, once the sender endpoint has executed send, it does not need to wait for any response from any receiver. So, if we were to try to keep a single owner throughout the message routing process, it would not make sense to keep ownership in the caller of send or otherwise, send would have to wait until all receivers are done processing the message, which would introduce an unnecessary round trip delay. On the other hand, if multiple receivers are subscribed to the topic, it also wouldn't make sense to assign unique ownership to any single one of them, as we don't know which one of them needs the message the longest. That would leave the routing infrastructure itself as the unique owner; but again, in that case, then the routing infrastructure would have to wait for all receivers to be done, while the infrastructure could have numerous messages to deliver to multiple threads, and it also wants to be able to pass off the message to receivers and be able to go to the next message to be delivered. Another alternative would be to keep a set of unique pointers to messages sent waiting for threads to process them, and have the receivers notify the message router when they're done; but that would also introduce unnecessary overhead.
On the other hand, by using shared_ptr here, once the routing infrastructure is done delivering messages to incoming queues of the endpoints, it can then release ownership to be shared between the various receivers. Then, the thread-safe reference counting ensures that the Message gets freed once all the receivers are done processing it. And in the case that there are subscribers on remote machines, the serialization and transmission component could be another shared owner of the message while it's doing its work; then, on the receiving machine(s), the receiving and deserialization component can pass off ownership of the Message copy it creates to shared ownership of the receivers on that machine.
In a CAD app, I use shared_ptr to save RAM and VRAM when multiple models happen to have a same mesh (e.g. after user copy-pasted these models). As a bonus, multiple threads can access meshes at the same time, because both shared_ptr and weak_ptr are thread safe when used correctly.
Below’s a trivial example. The real code is way more complex due to numerous reasons (GPU buffers, mouse picking, background processing triggered by some user input, and many others) but I hope that’s enough to give you an idea where shared_ptr is justified.
// Can be hundreds of megabytes in these vectors
class Mesh
{
std::string name;
std::vector<Vector3> vertices;
std::vector<std::array<uint32_t, 3>> indices;
BoundingBox bbox;
};
// Just 72 or 80 bytes, very cheap to copy.
// Can e.g. pass copies to another thread for background processing.
// A scene owns a collection of these things.
class Model
{
std::shared_ptr<Mesh> mesh;
Matrix transform;
};
In my program's user interface, I have the concept of "control point values" (a control point value represents the current state of a control on the hardware my program controls), and (of course) the concept of "widgets" (a widget is a GUI component that renders the current state of a control point to the monitor, for the user to see and/or manipulate).
Since it is a pretty elaborate system that it needs to control, we have
lots of different types of control point values (floats, ints, strings, booleans, binary blobs, etc)
lots of different types of widget (text displays, faders, meters, knobs, buttons, etc)
lots of different ways that a given widget could choose to render a particular control point value as text (upper case, lower case, more or fewer digits of precision, etc)
If we just did the obvious thing and wrote a new subclass every time we needed a new combination of the above, we'd end up with a geometric explosion of thousands of subclasses, and therefore a very large codebase that would be difficult to understand or maintain.
To avoid that, I separate out the knowledge of "how to translate a control point value into human-readable text in some particular way" into its own separate immutable object that can be used by anyone to do that translation, e.g.
// My abstract interface
class IControlPointToTextObject
{
public:
virtual std::string getTextForControlPoint(const ControlPoint & cp) const = 0;
};
// An example implementation
class RenderFloatingPointValueAsPercentage : public IControlPointToTextObject
{
public:
RenderFloatingPointValueAsPercentage(int precision) : m_precision(precision)
{
// empty
}
virtual std::string getTextForControlPoint(const ControlPoint & cp) const = 0
{
// code to create and return a percentage with (m_precision) digits after the decimal point goes here....
}
private:
const int m_precision;
};
... so far, so good; now e.g. when I want a text widget to display a control point value as a percentage with 3 digits of after the decimal point, I can do it like this:
TextWidget * myTextWidget = new TextWidget;
myTextWidget->setTextRenderer(std::unique_ptr<IControlPointToTextObject>(new RenderFloatingPointValueAsPercentage(3)));
... and I get what I want. But my GUIs can get rather elaborate, and they might have a large number (thousands) of widgets, and with the above approach I would have to create a separate RenderFloatingPointValueAsPercentage object for each widget, even though most of the RenderFloatingPointValueAsPercentage objects will end up being identical to each other. That's kind of wasteful, so I change my widget classes to accept a std::shared_ptr instead, and now I can do this:
std::shared_ptr<IControlPointToTextObject> threeDigitRenderer = std::make_shared<RenderFloatingPointValueAsPercentage>(3);
myWidget1->setTextRenderer(threeDigitRenderer);
myWidget2->setTextRenderer(threeDigitRenderer);
myWidget3->setTextRenderer(threeDigitRenderer);
[...]
No worries about object lifetimes, no dangling pointers, no memory leaks, no unnecessary creation of duplicate renderer objects. C'est bon :)
Take any lambda, called within a member function, f, of a class, C, where you want to deal with an object that you would pass into the lambda [&] as a reference. While you are waiting inside f for the lambda to finish, C goes out of scope. The function is gone and you have a dangling reference. Segmentation fault is as close as you get to defined behavior, when the lambda is next accessing the reference. You cannot pass the unique punter into the lambda. You couldn't access it from f once it's moved. The solution: shared pointer and [=]. I code the core of a database. We need shared pointers all the time in a multi-threaded infrastructure. Don't forget about the atomic reference counter. But your general scepticism is appreciated. Shared punters are used nearly always when one doesn't need them.
Suppose I want to implement a GLR parser for a language that is or contains a recursive "expression" definition. And the parsing must not just check whether the input conforms to the grammar, but also output something that can be used to do analysis, evaluations, compilations, etc. I'll need something to represent the result of each expression or subexpression grammar symbol. The actual semantic meaning of each grammar rule can be represented by polymorphism, so this will need to be some sort of pointer to a base class Expression.
The natural representation is then a std::shared_ptr<Expression>. An Expression object can be a subexpression of another compound Expression, in which case the compound Expression is the owner of the subexpression. Or an Expression object can be owned by the parse stack of the algorithm in progress, for a grammar production that has not yet been combined with other pieces. But not really both at the same time. If I were writing a LALR parser, I could probably do with std::unique_ptr<Expression>, transferring the subexpressions from the parse stack to the compound expression constructors as each grammar symbol is reduced.
The specific need for shared_ptr comes up with the GLR algorithm. At certain points, when there is more than one possible parse for the input scanned so far, the algorithm will duplicate the parse stack in order to try out tentative parses of each possibility. And as the tentative parsings proceed, each possiblity may need to use up some of those intermediate results from its own parse stack to form subexpressions of some compound expression, so now we might have the same Expression being used by both some number of parse stacks and some number of different compound Expression objects. Hopefully all but one tentative parsing will eventually fail, which means the failed parse stacks get discarded. The Expression objects directly and indirectly contained by discarded parse stacks should possibly be destroyed at that time, but some of them may be used directly or indirectly by other parse stacks.
It would be possible to do all this with just std::unique_ptr, but quite a bit more complicated. You could do a deep clone whenever parse stacks need to split, but that could be wasteful. You could have them owned by some other master container and have the parse stacks and/or compound expressions just use dumb pointers to them, but knowing when to clean them up would be difficult (and possibly end up essentially duplicating a simplified implementation of std::shared_ptr). I think std::shared_ptr is the clear winner here.
See this real life example. The current frame is shared across multiple consumers and with a smart pointer things get easy.
class frame { };
class consumer { public: virtual void draw(std::shared_ptr<frame>) = 0; };
class screen_consumer_t :public consumer { public: void draw(std::shared_ptr<frame>) override {} };
class matrox_consumer_t :public consumer { public: void draw(std::shared_ptr<frame>) override {} };
class decklink_consumer_t :public consumer { public: void draw(std::shared_ptr<frame>) override {} };
int main() {
std::shared_ptr<frame> current_frame = std::make_shared<frame>();
std::shared_ptr<consumer> screen_consumer = std::make_shared<screen_consumer_t>();
std::shared_ptr<consumer> matrox_consumer = std::make_shared<matrox_consumer_t>();
std::shared_ptr<consumer> decklink_consumer = std::make_shared<decklink_consumer_t>();
std::vector<consumer> consumers;
consumers.push_back(screen_consumer);
consumers.push_back(matrox_consumer);
consumers.push_back(decklink_consumer);
//screen_consumer->draw(current_frame);
//matrox_consumer->draw(current_frame);
//decklink_consumer->draw(current_frame);
for(auto c: consumers) c->draw(current_frame);
}
Edited:
Another example can be a Minimax tree, to avoid cyclic redundancy weak_ptr in conjunction with shared_ptr can be used:
struct node_t
{
std::unique_ptr<board_t> board_;
std::weak_ptr<node_t> parent_;
std::vector<std::shared_ptr<node_t>> children_;
};
Have you checked these articles about copy-on-write vector:
https://iheartcoding.net/blog/2016/07/11/copy-on-write-vector-in-c/
copy-on-write PIMPL:
https://crazycpp.wordpress.com/2014/09/13/pimplcow/
and generic copy-on-write pointer:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-on-write
All of them use shared_ptr internally.
std::shared_ptr is an implementation of reference counting technique in C++. For use-cases of reference counting see linked wikipedia article. One usage of reference counting is garbage collection in programming languages. So if you decide to write a new programming language with garbage collection in C++ you can implement it with std::shared_ptr, though you will also have to deal with cycles.
Simply put: there isn't really any.
For more detailed explanation, let's turn to formal reasoning. As we all know, C++ is a Turing-complete deterministic language. A popular simple example of equally computationally powerful tool is Brainfuck (often very convenient in establishing Turing-completeness of your favorite language of choice). If we look into Brainfuck's description (which is very small indeed, which makes it very handy for the purposes noted heretofore), we'll soon find out that there is not a single notion of anything resembling shared_ptr in there. So the answer is: no, there is no a real-life example where they would be absolutely required. Everything computable can be done without shared_ptrs.
If we continue the process thoroughly, we'll get rid equally easily of other unnecessary concepts, i.e. unique_ptr, std::unordered_map, exceptions, range-loops and so forth.

Singleton class across the whole project approach

I have a singleton class for logging purpose in my Qt project. In each class except the singleton one, there is a pointer point to the singleton object and a signal connected to an writing slot in the singleton object. Whichever class wants to write log info just emit that signal. The signals are queued so it's thread-safe.
Please critique this approach from OOP point of view, thanks.
=============================================================================================
Edit 1:
Thank you all your applies, listening to opposite opinions is always a big learning.
Let me explain more about my approach and what I did in my code so far:
Exactly as MikeMB pointer, the singleton class has a static function like get_instance() that returns a reference to that singleton. I stored it in a local pointer in each class's constructor, so it will be destroyed after the constructor returns. It is convenient for checking if I got a null pointer and makes the code more readable. I don't like something as this:
if(mySingletonClass::gerInstance() == NULL) { ... }
connect(gerInstance(), SIGNAL(write(QString)), this, SLOT(write(QString)));
because it is more expensive than this:
QPointer<mySingletonClass> singletonInstance = mySingletonClass::getInstance();
if(singletonInstance.isNull) { ... }
connect(singletonInstance, SIGNAL(write(QString)), this, SLOT(write(QString)));
Calling a function twice is more expensive than creating a local variable from ASM's point of view because of push, pop and return address calculation.
Here is my singleton class:
class CSuperLog : public QObject
{
Q_OBJECT
public:
// This static function creates its instance on the first call
// and returns it's own instance just created
// It only returns its own instance on the later calls
static QPointer<CSuperLog> getInstance(void); //
~CSuperLog();
public slots:
void writingLog(QString aline);
private:
static bool ready;
static bool instanceFlag;
static bool initSuccess;
static QPointer<CSuperLog> ptrInstance;
QTextStream * stream;
QFile * oFile;
QString logFile;
explicit CSuperLog(QObject *parent = 0);
};
I call getInstance() at the beginning of main() so make sure it is read immediately for each other class whenever they need to log important information.
MikeMB:
Your approach is making a middle man sitting in between, it makes the path of the logging info much longer because the signals in Qt are always queued except you make direct connection. The reason why I can't make direct connection here is it make the class non-thread-safe since I use threads in each other classes. Yes, someone will say you can use Mutex, but mutex also creates a queue when more than one thread competing on the same resource. Why don't you use the existing mechanism in Qt instead of making your own?
Thank you all of your posts!
=========================================================
Edit 2:
To Marcel Blanck:
I like your approach as well because you considered resource competition.
Almost in every class, I need signals and slots, so I need QObject, and this is why I choose Qt.
There should be only one instance for one static object, if I didn't get it wrong.
Using semaphores is same as using signals/slots in Qt, both generates message queue.
There always be pros and cons regarding the software design pattern and the application performance. Adding more layers in between makes your code more flexible, but decreases the performance significantly on those lower-configured hardware, making your application depending one most powerful hardware, and that's why most of modern OSes are written in pure C and ASM. How to balance them is really a big challenge.
Could you please explain a little bit more about your static Logger factory approach? Thanks.
I do not like singletons so much because it is always unclean to use them. I have even read job descriptions that say "Knowledge of design patterns while knowing that Singleton isn't one to use". Singleton leads to dependecy hell and if you ever want to change to a completely different logging approach (mabe for testing or production), while not destroying the old one you, need to change a lot.
Another problem with the approch is the usage of signals. Yes get thread savety for free, and do not interrupt the code execution so much but...
Every object you log from needs to be a QObject
If you hunt crashes your last logs will not be printed because the logger had no time to do it before the program crashed.
I would print directly. Maybe you can have a static Logger factory that returns a logger so you can have one logger object in every thread (memory impact will still be very small). Or you have one that is threadsave using semaphores and has a static interface. In both cases the logger should be used via an interface to be more flexible later.
Also make sure that your approach prints directly. Even printf writes to a buffer before being printed and you need to flush it every time or you might never find crashes under bad circumstances, if hunting for them.
Just my 2 cents.
I would consider separating the fact that a logger should be unique, and how the other classes get an instance of the logger class.
Creating and obtaining an instance of the logger could be handled in some sort of factory that internally encapsulates its construction and makes only one instance if need be.
Then, the way that the other classes get an instance of the logger could be handled via Dependency injection or by a static method defined on the aforementioned factory. Using dependency injection, you create the logger first, then inject it into the other classes once created.
A singleton usually has a static function like get_instance() that returns a reference to that singleton, so you don't need to store a pointer to the singleton in every object.
Furthermore it makes no sense, to let each object connect its log signal to the logging slot of the logging object itself, because that makes each and every class in your project dependent on your logging class. Instead, let a class just emit the signal with the log information and establish the connection somewhere central on a higher level (e.g. when setting up your system in the main function). So your other classes don't have to know who is listening (if at all) and you can easily modify or replace your logging class and mechanism.
Btw.: There are already pretty advanced logging libraries out there, so you should find out if you can use one of them or at least, how they are used and adapt that concept to your needs.
==========================
EDIT 1 (response to EDIT 1 of QtFan):
Sorry, apparently I miss understood you because I thought the pointer would be a class member and not only a local variable in the constructor which is of course fine.
Let me also clarify what I meant by making the connection on a higher level:
This was solely aimed at where you make the connection - i.e. where you put the line
connect(gerInstance(), SIGNAL(write(QString)), this, SLOT(write(QString)));
I was suggesting to put this somewhere outside the class e.g. into the main function. So the pseudo code would look something like this:
void main() {
create Thread1
create Thread2
create Thread3
create Logger
connect Thread1 signal to Logger slot
connect Thread2 signal to Logger slot
connect Thread3 signal to Logger slot
run Thread1
run Thread2
run Thread3
}
This has the advantage that your classes don't have to be aware of the kind of logger you are using and whether there is only one or multiple or no one at all. I think the whole idea about signals and slots is that the emitting object doesn't need to know where its signals are processed and the receiving class doesn't have to know where the signals are coming from.
Of course, this is only feasible, if you don't create your objects / threads dynamically during the program's run time. It also doesn't work, if you want to log during the creation of your objects.

OO Approach For Hardware Communication... Possible Singleton?

I am working on a project where I need to talk to a particular box over UDP. There will only ever be one box connected to the system at any given time. The connection should last the entire duration of the program.
I have written a class that works (yay!) in providing the necessary data to the hardware. However, my main problem is that now I have to account for the fact that someone (a programmer down the road who will more than likely just ignore all my very neat comments ;) ) may create more than one instance of this class. This will more than likely result in some hilarious and rather amusing crash where the hardware in question is wondering why it is receiving data from two sockets on the same machine. More troublesome is the fact that creating the object actually spawns a thread that periodically sends updates. So you can imagine if my imaginary future programmer does something like create a linked list of these objects (after all, this is C++ and we have the ability to do such things) the CPU might not be very happy after a while.
As a result, I turn to you... the more experienced people of SO who have seen such issues in the past. I have debated creating a singleton to handle all of this, but some of my readings lead me to believe that this might not be the way to go. There is a TON of information regarding them on the internet, and it's almost like asking a highly sensitive political question based on the responses I've seen.
An alternative I've developed that will preserve as much code as possible is to just use a static bool to keep track if there is an active thread passing data to the hardware. However, I suspect my approach can lead to race conditions in the case where I have competing threads attempting to access the class at the same time. Here's what I have thus far:
// in MyClass.cpp:
static bool running_ = false; // declared in the class in the .h, but defined here
MyClass::MyClass() {
// various initialization stuff you don't care about goes here
if (pthread_create(mythread_, NULL, MyThreadFunc, this) != 0) {
// error
}
else {
// no error
}
}
static void* MyClass::MyThreadFunc(void* args) {
MyClass myclass = static_cast<MyClass>(args);
// now I have access to all the stuff in MyClass
// do various checks here to make sure I can talk to the box
if (!running_) {
running_ = true;
// open a connection
while (!terminate) { // terminate is a flag set to true in the destructor
// update the hardware via UDP
}
// close the socket
running_ = false;
}
}
While I certainly note that this will check for only one instance being active, there is still the possibility that two concurrent threads will access the !running_ check at the same time and therefore both open the connection.
As a result, I'm wondering what my options are here? Do I implement a singleton? Is there a way I can get the static variable to work? Alternatively, do I just comment about this issue and hope that the next programmer understands to not open two instances to talk to the hardware?
As always, thanks for the help!
Edited to add:
I just had another idea pop into my mind... what if the static bool was a static lock instead? That way, I could set the lock and then just have subsequent instances attempt to get the lock and if they failed, just return a zombie class... Just a thought...
You're right, asking about singleton is likely to start a flamewar, that will not make you any wiser. You better make up your mind yourself. It's not that hard really if you are aware of the primary principles.
For your case I'd skip that whole branch as irrelevant, as your post is motivated by FEAR. Fear from a speculative issue. So let me just advise you on that: relax. You can't fight idiots. As soon as you invent some fool-proof schema, the universe evolves and will produce a better idiot that will go around it. Not worth the effort. Leave the idiot problem to the management and HR, to keep them employed elsewhere.
Your task is to provide working solution and proper documentation on how to use it (ideally with tests and examples too). If you document usage to create just a single instance of your stuff, and doing the listed init and teardown steps, you can just expext that as followed -- or if not it be the next guy's problem.
Most of the real life grief comes NOT from dismissing dox, but that dox not present or is inaccurate. So just do that part properly.
Once done, certainly nothing forbids you to ass a few static or runtime asserts on preconditions: it's not hard to count your class' instances and assert it will not go over 1.
What if you have two instances of the hardware itself? [I know you say it will only be one - but I've been there, done that on the aspect of "It's only ever going to be one!! Oh, <swearword>, now we need to use two..."].
Of course, your if(running_) is a race-condition. You really should use some sort of atomic type, so that you don't get two attempts to start the class at once. That also won't stop someone from trying to start two instances of the overall program.
Returning a zombie class seems like a BAD solution - throwing an exception, returning an error value, or some such would be a much better choice.
Would it be possible to have "the other side" control the number of connections? In other words, if a second instance tries to communicate, it gets an error back from the hardware that receives the message "Sorry, already have a connection"?
Sorry if this isn't really "an answer".
First, I do not think you can really protect anything from this imaginary future developer if he's so much into breaking your code. Comments/doc should do the trick. If he misses them, the hardware (or the code) will likely crash, and he will notice. Moreover, if he as a good reason to reuse your class (like connecting to some other hardwares of the same kind), you do not want to block him with nasty hidden tricks.
This said, for your example, I would consider using an atomic<bool> to avoid any concurrency issue, and use the compare_exchange member function instead of if(!running) running = true:
static std::atomic<bool> running;
...
bool expected = false;
if(running.compare_exchange_strong(expected, true)) {
...

Does ScopeGuard use really lead to better code?

I came across this article written by Andrei Alexandrescu and Petru Marginean many years ago, which presents and discusses a utility class called ScopeGuard for writing exception-safe code. I'd like to know if coding with these objects truly leads to better code or if it obfuscates error handling, in that perhaps the guard's callback would be better presented in a catch block? Does anyone have any experience using these in actual production code?
It definitely improves your code. Your tentatively formulated claim, that it's obscure and that code would merit from a catch block is simply not true in C++ because RAII is an established idiom. Resource handling in C++ is done by resource acquisition and garbage collection is done by implicit destructor calls.
On the other hand, explicit catch blocks would bloat the code and introduce subtle errors because the code flow gets much more complex and resource handling has to be done explicitly.
RAII (including ScopeGuards) isn't an obscure technique in C++ but firmly established best-practice.
Yes.
If there is one single piece of C++ code that I could recommend every C++ programmer spend 10 minutes learning, it is ScopeGuard (now part of the freely available Loki library).
I decided to try using a (slightly modified) version of ScopeGuard for a smallish Win32 GUI program I was working on. Win32 as you may know has many different types of resources that need to be closed in different ways (e.g. kernel handles are usually closed with CloseHandle(), GDI BeginPaint() needs to be paired with EndPaint(), etc.) I used ScopeGuard with all these resources, and also for allocating working buffers with new (e.g. for character set conversions to/from Unicode).
What amazed me was how much shorter the program was. Basically, it's a win-win: your code gets shorter and more robust at the same time. Future code changes can't leak anything. They just can't. How cool is that?
I often use it for guarding memory usage, things that need to be freed that were returned from the OS. For example:
DATA_BLOB blobIn, blobOut;
blobIn.pbData=const_cast<BYTE*>(data);
blobIn.cbData=length;
CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &blobOut);
Guard guardBlob=guardFn(::LocalFree, blobOut.pbData);
// do stuff with blobOut.pbData
I think above answers lack one important note. As others have pointed out, you can use ScopeGuard in order to free allocated resources independent of failure (exception). But that might not be the only thing you might want to use scope guard for. In fact, the examples in linked article use ScopeGuard for a different purpose: transcations. In short, it might be useful if you have multiple objects (even if those objects properly use RAII) that you need to keep in a state that's somehow correlated. If change of state of any of those objects results in an exception (which, I presume, usually means that its state didn't change) then all changes already applied need to be rolled back. This creates it's own set of problems (what if a rollback fails as well?). You could try to roll out your own class that manages such correlated objects, but as the number of those increases it would get messy and you would probably fall back to using ScopeGuard internally anyway.
Yes.
It was so important in C++ that even a special syntax for it in D:
void somefunction() {
writeln("function enter");
// c++ has similar constructs but not in syntax level
scope(exit) writeln("function exit");
// do what ever you do, you never miss the function exit output
}
I haven't used this particular template but I've used something similar before. Yes, it does lead to clearer code when compared to equally robust code implemented in different ways.
I have to say, no, no it does not. The answers here help to demonstrate why it's a genuinely awful idea. Resource handling should be done through re-usable classes. The only thing they've achieved by using a scope guard is to violate DRY up the wazoo and duplicate their resource freeing code all over their codebase, instead of writing one class to handle the resource and then that's it, for the whole lot.
If scope guards have any actual uses, resource handling is not one of them. They're massively inferior to plain RAII in that case, since RAII is deduplicated and automatic and scope guards are manual code duplication or bust.
My experience shows that usage of scoped_guard is far inferior to any of the short reusable RAII classes that you can write by hand.
Before trying the scoped_guard, I had written RAII classes to
set GLcolor or GLwidth back to the original, once I've drawn a shape
make sure a file has fclosed once I had fopened it.
reset a mouse pointer to its initial state, after I've changed it to gears/hourgrlass during a execution of a slow function
reset the sorting state of a QListView's back to its previous state, once I've temporarily finished with altering its QListViewItems -- I did not want the list to reorder itself everytime I changed the text of a single item...
using simple RAII class
Here's how my code looked like with my hand-crafted RAII classes:
class scoped_width {
int m_old_width;
public:
scoped_width(int w) {
m_old_width = getGLwidth();
setGLwidth(w);
}
~scoped_width() {
setGLwidth(m_old_width);
}
};
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
auto guard = scoped_width(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_width sets GLwidth back to 1 here
Very simple implementation for scoped_width, and quite reusable.
Very simple and readable from the consumer side, also.
using scoped_guard (C++14)
Now, with the scoped_guard, I have to capture the existing value in the introducer ([]) in order to pass it to the guard's callback:
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
auto guard = sg::make_scoped_guard([w=getGLwidth()](){ setGLwidth(w); }); // capture current GLwidth in order to set it back
setGLwidth(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_guard sets GLwidth back to 1 here
The above doesn't even work on C++11.
Not to mention that trying to introduce the state to the lambda this way hurts my eyes.
using scoped_guard (C++11)
In C++11 you have to do this:
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
int previous_width = getGLwidth(); // explicitly capture current width
auto guard = sg::make_scoped_guard([=](){ setGLwidth(previous_width); }); // pass it to lambda in order to set it back
setGLwidth(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_guard sets GLwidth back to 1 here
As you can see,
the scoped_guard snoppet requires
3 lines to keep previous value (state) and set it to a new one, and
2 stack variables (previous_width and guard, again) to hold the previous state
the hand-crafted RAII class requires
1 readable line to set new state and keep the previous one, and
1 stack variable (guard) to hold the previous state.
Conclusion
I think that examples such as
void some_function() {
sg::scoped_guard([](){ cout << "this is printed last"; }
cout << "this is printed first";
}
are no proof of the usefullness of scoped_guard.
I hope that somebody can show me why I don't get the expected gain from scoped_guard.
I am convinced that RAII can be exploited better by writing short hand-crafted classes, than using the more generic but hard to use scoped_guard