Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it OK for a class constructor to block forever?

Let's say I have an object that provides some sort of functionality in an infinite loop.

Is is acceptable to just put the infinite loop in the constructor?

Example:

class Server {     public:     Server() {         for(;;) {             //...         }     } }; 

Or is there an inherent initialization problem in C++ if the constructor never completes?

(The idea is that to run a server you just say Server server;, possibly in a thread somewhere...)

like image 201
CaptainCodeman Avatar asked Nov 07 '20 11:11

CaptainCodeman


People also ask

What a constructor should not do?

Don't call delete this or the destructor in the constructor. Don't use init()/cleanup() members. If you have to call init() every time you create an instance, everything in init() should be in the constructor.

How many times can the constructor be invoked?

10. How many times can a constructor be called during lifetime of the object? As many times as we call it. Only once.

Can a constructor fail?

A constructor may well open a file (not necessarily a bad idea) and may throw if the file-open fails, or if the input file does not contain compatible data. It is reasonable behaviour for a constructor to throw an exception, however you will then be limited as to its use.

How should a constructor handle a failure?

The best way to signal constructor failure is therefore to throw an exception. If you don't have the option of using exceptions, the "least bad" work-around is to put the object into a "zombie" state by setting an internal status bit so the object acts sort of like it's dead even though it is technically still alive.


2 Answers

It's not wrong per standard, it's just a bad design.

Constructors don't usually block. Their purpose is to take a raw chunk of memory, and transform it into a valid C++ object. Destructors do the opposite: they take valid C++ objects and turn them back into raw chunks of memory.

If your constructor blocks forever (emphasis on forever), it does something different than just turn a chunk of memory into an object. It's ok to block for a short time (a mutex is a perfect example of it), if this serves the construction of the object. In your case, it looks like your constructor is accepting and serving clients. This is not turning memory into objects.

I suggest you split the constructor into a "real" constructor that builds a server object and another start method that serves clients (by starting an event loop).

ps: In some cases you have to execute the functionality/logic of the object separately from the constructor, for example if your class inherit from std::enable_shared_from_this.

like image 169
David Haim Avatar answered Sep 18 '22 06:09

David Haim


It's allowed. But like any other infinite loop, it must have observable side effects, otherwise you get undefined behavior.

Calling the networking functions counts as "observable side effects", so you're safe. This rule only bans loops that either do literally nothing, or just shuffle data around without interacting with the outside world.

like image 35
HolyBlackCat Avatar answered Sep 20 '22 06:09

HolyBlackCat