Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a multiple-producer single-consumer (MPSC) queue implementation #753

Merged
merged 5 commits into from
Jun 23, 2021

Conversation

LaurentiuCristofor
Copy link
Contributor

@senderista suggested using an MPSC queue implementation from 1024cores.net:
https://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue

This PR includes a C++ implementation that is derived from that 1024cores.net C implementation.

I changed the current use of a different queue implementation to this new one.

The code requires a specific license notice to be distributed, so I added that notice under a new licenses folder under production. If we have any other bits of code that require specific licenses to be distributed, please add them under this folder and ensure that the name of their containing folder describes the code to which they apply.

Copy link
Contributor

@simone-gaia simone-gaia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the licenses folder, It could be placed in the root directory.

production/inc/gaia_internal/common/queue.hpp Show resolved Hide resolved
Comment on lines 110 to 115
protected:
void enqueue_internal(mpsc_queue_node_t<T>* node);
mpsc_queue_node_t<T>* dequeue_internal();

protected:
std::atomic<mpsc_queue_node_t<T>*> volatile m_head;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is everything protected? This class does not seem to have subclasses.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going with protected indicates that I don't mind having derived classes access this information. Going with private means that I really want to keep the implementation internal, which is not the case here.

When you don't know what you want, protected makes more sense. Private should be used when you really don't want the variables/methods to be used outside a class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could agree if this was a public-facing API that and we did not have control over the sources (even in that case, you should design for "extensions" instead of giving access to the internal state of the class).

Since we do have control over the sources, I think is better to make everything private UNTIL there is a reason not to do so. When that happens, only the fields that need to be exposed to the subclass will be put in the protected section. This helps to understand the scope of a given field.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing is: if I see protected I assume there is a subclass, or I assume this class is designed to be subclassed. Weh I've seen protected here I started looking for the subclass. I think putting protected without a strong reason causes more harm than good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if it were public API, private would be a safer choice than protected, because protected would still expose the method/variable as part of the interface (for deriving classes), so you'd be forced to continue exposing what you've offered as protected.

But internally, I don't need to protect the code from its developers. And too often, when you derive a class, you want to access its internals directly, instead of exposing all access methods through public methods.

If the class has no derived classes, protected works just like private. And if it gets derived, it doesn't require updating to turn private fields into protected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no point in using protected id there are no subclasses

The point is that you allow any subclasses to use these fields.

It does matter because the subclass may change the value of the fields hence I need to be extra carful when using them from upper classes.

A subclass could also change the value of private fields through the public interface. I think you want to say something different, but I'm not sure exactly what that is.

Because seeing those protected fields I must assume some subclasses may use them and I must check what they are used for. To me it's scope-creep.

You only need to do this if you intend to change the class. In which case, you'd do enough look-around to figure out how it works that you couldn't avoid finding out if it's sub-classed or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@senderista : Don't mind us. :)

I hope that the comments I added help explain the algorithm and my modifications to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't have time to review this, but I did notice that "head" denotes the end of the queue used to enqueue items, and "tail" denotes the end of the queue used to dequeue items. This is the reverse of the normal convention and I find it very confusing when reading the code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I see the original code uses the same convention. It's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I kept the naming close to the original to make it easier to do a side-by-side comparison.

production/inc/gaia_internal/common/queue.inc Show resolved Hide resolved
Copy link
Contributor

@simone-gaia simone-gaia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, besides the protected thing which I don't really like. But I don't consider it a blocker.

@LaurentiuCristofor LaurentiuCristofor merged commit 0fa1546 into master Jun 23, 2021
@LaurentiuCristofor LaurentiuCristofor deleted the laur_queue branch June 23, 2021 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants