Simple raw buffer queue implementationQueue Implementation(nearly) lock-free job queue of dynamic size...
My boss asked me to take a one-day class, then signs it up as a day off
How do ultrasonic sensors differentiate between transmitted and received signals?
Is there any significance to the Valyrian Stone vault door of Qarth?
How to prevent YouTube from showing already watched videos?
Is there a problem with hiding "forgot password" until it's needed?
Should my PhD thesis be submitted under my legal name?
Is a naturally all "male" species possible?
The most efficient algorithm to find all possible integer pairs which sum to a given integer
Organic chemistry Iodoform Reaction
Is it okay / does it make sense for another player to join a running game of Munchkin?
Installing PowerShell on 32-bit Kali OS fails
Blender - show edges angles “direction”
Simulating a probability of 1 of 2^N with less than N random bits
Hostile work environment after whistle-blowing on coworker and our boss. What do I do?
Invariance of results when scaling explanatory variables in logistic regression, is there a proof?
Did US corporations pay demonstrators in the German demonstrations against article 13?
What is the opposite of 'gravitas'?
How to check participants in at events?
Visiting the UK as unmarried couple
What will be the benefits of Brexit?
Pronouncing Homer as in modern Greek
Can a controlled ghast be a leader of a pack of ghouls?
Identify a stage play about a VR experience in which participants are encouraged to simulate performing horrific activities
Calculating the number of days between 2 dates in Excel
Simple raw buffer queue implementation
Queue Implementation(nearly) lock-free job queue of dynamic size (multiple read/write)STL queue implementationTemplated queue implementationBoost::pool based STL vector allocatorC++ Queue ImplementationSimple Queue ImplementationQueue With Variable Size BufferQueue Implementation in C++Implementation of a queue
$begingroup$
I am trying to implement a simple raw queue in C++. This is what I have come up with
#include <queue>
#include <cstdint>
#include <array>
#include <cstring>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
using char_msg = std::array<char, max_msg_size>;
std::queue<char_msg> char_queue;
public:
simple_queue() = default;
~simple_queue() = default;
simple_queue(simple_queue&&) = default;
simple_queue& operator=(simple_queue&&) = default;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_msg tmp_msg;
std::memcpy(&tmp_msg, buff, size_to_copy);
char_queue.push(std::move(tmp_msg));
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
const uint32_t size_to_copy = std::min(max_msg_size, size);
std::memcpy(buff, &char_queue.front(), size_to_copy);
char_queue.pop();
return size_to_copy;
}
};
Note that I am trying to implement this queue just to store raw char buffers. As far as I understand making it a template does not make sense in this case.
I have played with it a bit and it seems to work as I expect.
- What can I change with this implementation?
- Does it make sense to use a custom allocator in here? I am allocating memory every time I write to the queue; how can I use a custom allocator to allocate some default chunk of memory when the queue is constructed?
c++ performance queue
$endgroup$
add a comment |
$begingroup$
I am trying to implement a simple raw queue in C++. This is what I have come up with
#include <queue>
#include <cstdint>
#include <array>
#include <cstring>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
using char_msg = std::array<char, max_msg_size>;
std::queue<char_msg> char_queue;
public:
simple_queue() = default;
~simple_queue() = default;
simple_queue(simple_queue&&) = default;
simple_queue& operator=(simple_queue&&) = default;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_msg tmp_msg;
std::memcpy(&tmp_msg, buff, size_to_copy);
char_queue.push(std::move(tmp_msg));
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
const uint32_t size_to_copy = std::min(max_msg_size, size);
std::memcpy(buff, &char_queue.front(), size_to_copy);
char_queue.pop();
return size_to_copy;
}
};
Note that I am trying to implement this queue just to store raw char buffers. As far as I understand making it a template does not make sense in this case.
I have played with it a bit and it seems to work as I expect.
- What can I change with this implementation?
- Does it make sense to use a custom allocator in here? I am allocating memory every time I write to the queue; how can I use a custom allocator to allocate some default chunk of memory when the queue is constructed?
c++ performance queue
$endgroup$
add a comment |
$begingroup$
I am trying to implement a simple raw queue in C++. This is what I have come up with
#include <queue>
#include <cstdint>
#include <array>
#include <cstring>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
using char_msg = std::array<char, max_msg_size>;
std::queue<char_msg> char_queue;
public:
simple_queue() = default;
~simple_queue() = default;
simple_queue(simple_queue&&) = default;
simple_queue& operator=(simple_queue&&) = default;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_msg tmp_msg;
std::memcpy(&tmp_msg, buff, size_to_copy);
char_queue.push(std::move(tmp_msg));
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
const uint32_t size_to_copy = std::min(max_msg_size, size);
std::memcpy(buff, &char_queue.front(), size_to_copy);
char_queue.pop();
return size_to_copy;
}
};
Note that I am trying to implement this queue just to store raw char buffers. As far as I understand making it a template does not make sense in this case.
I have played with it a bit and it seems to work as I expect.
- What can I change with this implementation?
- Does it make sense to use a custom allocator in here? I am allocating memory every time I write to the queue; how can I use a custom allocator to allocate some default chunk of memory when the queue is constructed?
c++ performance queue
$endgroup$
I am trying to implement a simple raw queue in C++. This is what I have come up with
#include <queue>
#include <cstdint>
#include <array>
#include <cstring>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
using char_msg = std::array<char, max_msg_size>;
std::queue<char_msg> char_queue;
public:
simple_queue() = default;
~simple_queue() = default;
simple_queue(simple_queue&&) = default;
simple_queue& operator=(simple_queue&&) = default;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_msg tmp_msg;
std::memcpy(&tmp_msg, buff, size_to_copy);
char_queue.push(std::move(tmp_msg));
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
const uint32_t size_to_copy = std::min(max_msg_size, size);
std::memcpy(buff, &char_queue.front(), size_to_copy);
char_queue.pop();
return size_to_copy;
}
};
Note that I am trying to implement this queue just to store raw char buffers. As far as I understand making it a template does not make sense in this case.
I have played with it a bit and it seems to work as I expect.
- What can I change with this implementation?
- Does it make sense to use a custom allocator in here? I am allocating memory every time I write to the queue; how can I use a custom allocator to allocate some default chunk of memory when the queue is constructed?
c++ performance queue
c++ performance queue
asked yesterday
AliAli
20129
20129
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
You are not allocating per se when when writing to the queue. std::array is backed by a plain C-array on the stack, that gets moved.
So you only ever allocate depending on the underlying container the std::queue is based on. By default this is a std::deque.
I do not really understand the need for the std::array in the type though. Why not just use a std::string and limit the size of it to 4096? There is even a constructor that does explicitely that string (const char* s, size_t n)
Before I get to the Code there are some other things I would like to mention:
why are you not useing std::copy instead of memcpy. The former works better with C++ and will in the end almost always end up as memcpy?
You do not need to define the special member functions. In fact you have forgotten 2 of then, aka copy assignment and copy constructor. Why do I say forgotten? Because there is no way to tell. So If you want your queue to be move only then you should actually
deletethose special member functions you dont want.In your read function you never check whether the size you want to read is actually valid. Is that intendend? If so why? A
std::arrayis not initialized so the memory in it that is not written by you will be random. You are not writing to it but you are copying it around. So you should actually take the minimum out ofsizeandqueue.front().size()std::stringhas a member functionstd::string::copythat copyies a certain amount of chars to a buffer (http://www.cplusplus.com/reference/string/string/copy/). I would suggest to use that for writing back to the buffer
That leads me to the following:
#include <string>
#include <queue>
#include <vector>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
std::queue<std::string, std::vector<std::string>> char_queue;
public:
simple_queue(const simple_queue&) = delete;
simple_queue& operator=(const simple_queue&) = delete;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_queue.emplace(buff, size_to_copy);
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
std::string& msg = char_queue.front();
const uint32_t size_to_copy = std::min(msg, size);
msg.copy(buff, size_to_copy, 0);
char_queue.pop();
return size_to_copy;
}
};
EDIT:
I forgot to mention, that now you should use a std::vector as backing of the queue as your are not storing a gargantuan array but rather a mall std::string.
Note that it actually ends up being the same. The std::deque based std::array implementation is backed by a linked list, so each array ends up in a node of a linked list, which is kind of similar to the separate allocation of the std::string
$endgroup$
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every.emplace(buff, size_to_copy)the allocator forstd::stringis called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so withstd::arrayand that's why I opted to use that instead ofstd::string.
$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to usestd::vector, you mean I should use a vector ofchars?
$endgroup$
– Ali
yesterday
1
$begingroup$
@Alistd::queueis a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default containerstd::dequewithstd::vector
$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array intostd::dequenode
$endgroup$
– miscco
yesterday
|
show 3 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216097%2fsimple-raw-buffer-queue-implementation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
You are not allocating per se when when writing to the queue. std::array is backed by a plain C-array on the stack, that gets moved.
So you only ever allocate depending on the underlying container the std::queue is based on. By default this is a std::deque.
I do not really understand the need for the std::array in the type though. Why not just use a std::string and limit the size of it to 4096? There is even a constructor that does explicitely that string (const char* s, size_t n)
Before I get to the Code there are some other things I would like to mention:
why are you not useing std::copy instead of memcpy. The former works better with C++ and will in the end almost always end up as memcpy?
You do not need to define the special member functions. In fact you have forgotten 2 of then, aka copy assignment and copy constructor. Why do I say forgotten? Because there is no way to tell. So If you want your queue to be move only then you should actually
deletethose special member functions you dont want.In your read function you never check whether the size you want to read is actually valid. Is that intendend? If so why? A
std::arrayis not initialized so the memory in it that is not written by you will be random. You are not writing to it but you are copying it around. So you should actually take the minimum out ofsizeandqueue.front().size()std::stringhas a member functionstd::string::copythat copyies a certain amount of chars to a buffer (http://www.cplusplus.com/reference/string/string/copy/). I would suggest to use that for writing back to the buffer
That leads me to the following:
#include <string>
#include <queue>
#include <vector>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
std::queue<std::string, std::vector<std::string>> char_queue;
public:
simple_queue(const simple_queue&) = delete;
simple_queue& operator=(const simple_queue&) = delete;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_queue.emplace(buff, size_to_copy);
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
std::string& msg = char_queue.front();
const uint32_t size_to_copy = std::min(msg, size);
msg.copy(buff, size_to_copy, 0);
char_queue.pop();
return size_to_copy;
}
};
EDIT:
I forgot to mention, that now you should use a std::vector as backing of the queue as your are not storing a gargantuan array but rather a mall std::string.
Note that it actually ends up being the same. The std::deque based std::array implementation is backed by a linked list, so each array ends up in a node of a linked list, which is kind of similar to the separate allocation of the std::string
$endgroup$
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every.emplace(buff, size_to_copy)the allocator forstd::stringis called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so withstd::arrayand that's why I opted to use that instead ofstd::string.
$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to usestd::vector, you mean I should use a vector ofchars?
$endgroup$
– Ali
yesterday
1
$begingroup$
@Alistd::queueis a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default containerstd::dequewithstd::vector
$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array intostd::dequenode
$endgroup$
– miscco
yesterday
|
show 3 more comments
$begingroup$
You are not allocating per se when when writing to the queue. std::array is backed by a plain C-array on the stack, that gets moved.
So you only ever allocate depending on the underlying container the std::queue is based on. By default this is a std::deque.
I do not really understand the need for the std::array in the type though. Why not just use a std::string and limit the size of it to 4096? There is even a constructor that does explicitely that string (const char* s, size_t n)
Before I get to the Code there are some other things I would like to mention:
why are you not useing std::copy instead of memcpy. The former works better with C++ and will in the end almost always end up as memcpy?
You do not need to define the special member functions. In fact you have forgotten 2 of then, aka copy assignment and copy constructor. Why do I say forgotten? Because there is no way to tell. So If you want your queue to be move only then you should actually
deletethose special member functions you dont want.In your read function you never check whether the size you want to read is actually valid. Is that intendend? If so why? A
std::arrayis not initialized so the memory in it that is not written by you will be random. You are not writing to it but you are copying it around. So you should actually take the minimum out ofsizeandqueue.front().size()std::stringhas a member functionstd::string::copythat copyies a certain amount of chars to a buffer (http://www.cplusplus.com/reference/string/string/copy/). I would suggest to use that for writing back to the buffer
That leads me to the following:
#include <string>
#include <queue>
#include <vector>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
std::queue<std::string, std::vector<std::string>> char_queue;
public:
simple_queue(const simple_queue&) = delete;
simple_queue& operator=(const simple_queue&) = delete;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_queue.emplace(buff, size_to_copy);
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
std::string& msg = char_queue.front();
const uint32_t size_to_copy = std::min(msg, size);
msg.copy(buff, size_to_copy, 0);
char_queue.pop();
return size_to_copy;
}
};
EDIT:
I forgot to mention, that now you should use a std::vector as backing of the queue as your are not storing a gargantuan array but rather a mall std::string.
Note that it actually ends up being the same. The std::deque based std::array implementation is backed by a linked list, so each array ends up in a node of a linked list, which is kind of similar to the separate allocation of the std::string
$endgroup$
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every.emplace(buff, size_to_copy)the allocator forstd::stringis called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so withstd::arrayand that's why I opted to use that instead ofstd::string.
$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to usestd::vector, you mean I should use a vector ofchars?
$endgroup$
– Ali
yesterday
1
$begingroup$
@Alistd::queueis a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default containerstd::dequewithstd::vector
$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array intostd::dequenode
$endgroup$
– miscco
yesterday
|
show 3 more comments
$begingroup$
You are not allocating per se when when writing to the queue. std::array is backed by a plain C-array on the stack, that gets moved.
So you only ever allocate depending on the underlying container the std::queue is based on. By default this is a std::deque.
I do not really understand the need for the std::array in the type though. Why not just use a std::string and limit the size of it to 4096? There is even a constructor that does explicitely that string (const char* s, size_t n)
Before I get to the Code there are some other things I would like to mention:
why are you not useing std::copy instead of memcpy. The former works better with C++ and will in the end almost always end up as memcpy?
You do not need to define the special member functions. In fact you have forgotten 2 of then, aka copy assignment and copy constructor. Why do I say forgotten? Because there is no way to tell. So If you want your queue to be move only then you should actually
deletethose special member functions you dont want.In your read function you never check whether the size you want to read is actually valid. Is that intendend? If so why? A
std::arrayis not initialized so the memory in it that is not written by you will be random. You are not writing to it but you are copying it around. So you should actually take the minimum out ofsizeandqueue.front().size()std::stringhas a member functionstd::string::copythat copyies a certain amount of chars to a buffer (http://www.cplusplus.com/reference/string/string/copy/). I would suggest to use that for writing back to the buffer
That leads me to the following:
#include <string>
#include <queue>
#include <vector>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
std::queue<std::string, std::vector<std::string>> char_queue;
public:
simple_queue(const simple_queue&) = delete;
simple_queue& operator=(const simple_queue&) = delete;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_queue.emplace(buff, size_to_copy);
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
std::string& msg = char_queue.front();
const uint32_t size_to_copy = std::min(msg, size);
msg.copy(buff, size_to_copy, 0);
char_queue.pop();
return size_to_copy;
}
};
EDIT:
I forgot to mention, that now you should use a std::vector as backing of the queue as your are not storing a gargantuan array but rather a mall std::string.
Note that it actually ends up being the same. The std::deque based std::array implementation is backed by a linked list, so each array ends up in a node of a linked list, which is kind of similar to the separate allocation of the std::string
$endgroup$
You are not allocating per se when when writing to the queue. std::array is backed by a plain C-array on the stack, that gets moved.
So you only ever allocate depending on the underlying container the std::queue is based on. By default this is a std::deque.
I do not really understand the need for the std::array in the type though. Why not just use a std::string and limit the size of it to 4096? There is even a constructor that does explicitely that string (const char* s, size_t n)
Before I get to the Code there are some other things I would like to mention:
why are you not useing std::copy instead of memcpy. The former works better with C++ and will in the end almost always end up as memcpy?
You do not need to define the special member functions. In fact you have forgotten 2 of then, aka copy assignment and copy constructor. Why do I say forgotten? Because there is no way to tell. So If you want your queue to be move only then you should actually
deletethose special member functions you dont want.In your read function you never check whether the size you want to read is actually valid. Is that intendend? If so why? A
std::arrayis not initialized so the memory in it that is not written by you will be random. You are not writing to it but you are copying it around. So you should actually take the minimum out ofsizeandqueue.front().size()std::stringhas a member functionstd::string::copythat copyies a certain amount of chars to a buffer (http://www.cplusplus.com/reference/string/string/copy/). I would suggest to use that for writing back to the buffer
That leads me to the following:
#include <string>
#include <queue>
#include <vector>
class simple_queue
{
private:
static constexpr uint32_t max_msg_size = 4096;
std::queue<std::string, std::vector<std::string>> char_queue;
public:
simple_queue(const simple_queue&) = delete;
simple_queue& operator=(const simple_queue&) = delete;
uint32_t write(const char* const buff, const uint32_t size) noexcept
{
const uint32_t size_to_copy = std::min(max_msg_size, size);
char_queue.emplace(buff, size_to_copy);
return size_to_copy;
}
uint32_t read(char* const buff, const uint32_t size) noexcept
{
if (char_queue.empty())
{
return 0;
}
std::string& msg = char_queue.front();
const uint32_t size_to_copy = std::min(msg, size);
msg.copy(buff, size_to_copy, 0);
char_queue.pop();
return size_to_copy;
}
};
EDIT:
I forgot to mention, that now you should use a std::vector as backing of the queue as your are not storing a gargantuan array but rather a mall std::string.
Note that it actually ends up being the same. The std::deque based std::array implementation is backed by a linked list, so each array ends up in a node of a linked list, which is kind of similar to the separate allocation of the std::string
edited yesterday
answered yesterday
misccomiscco
3,467517
3,467517
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every.emplace(buff, size_to_copy)the allocator forstd::stringis called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so withstd::arrayand that's why I opted to use that instead ofstd::string.
$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to usestd::vector, you mean I should use a vector ofchars?
$endgroup$
– Ali
yesterday
1
$begingroup$
@Alistd::queueis a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default containerstd::dequewithstd::vector
$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array intostd::dequenode
$endgroup$
– miscco
yesterday
|
show 3 more comments
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every.emplace(buff, size_to_copy)the allocator forstd::stringis called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so withstd::arrayand that's why I opted to use that instead ofstd::string.
$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to usestd::vector, you mean I should use a vector ofchars?
$endgroup$
– Ali
yesterday
1
$begingroup$
@Alistd::queueis a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default containerstd::dequewithstd::vector
$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array intostd::dequenode
$endgroup$
– miscco
yesterday
2
2
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
You should not use "EDIT tags"; they are only confusing and distracting for people who come to the question or answer for the first time. Edits happen all the time, and anyone interested can just click to see the whole post history.
$endgroup$
– Juho
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every
.emplace(buff, size_to_copy) the allocator for std::string is called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so with std::array and that's why I opted to use that instead of std::string.$endgroup$
– Ali
yesterday
$begingroup$
Thanks, all of your points are valid. I have updated the implementation and after running benchmarks it is performing much better. However there is still something I would like to improve. With every
.emplace(buff, size_to_copy) the allocator for std::string is called, I would like to get rid of allocation and have it use a pre allocated chunk of memory. I was under the impression it might be easier to do so with std::array and that's why I opted to use that instead of std::string.$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to use
std::vector, you mean I should use a vector of chars?$endgroup$
– Ali
yesterday
$begingroup$
@miscco BTW, I did not get why you've mentioned to use
std::vector, you mean I should use a vector of chars?$endgroup$
– Ali
yesterday
1
1
$begingroup$
@Ali
std::queue is a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default container std::deque with std::vector$endgroup$
– miscco
yesterday
$begingroup$
@Ali
std::queue is a container-adaptor. The second template argument it takes is the underlying container. Consequently, in the example i replaced the default container std::deque with std::vector$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array into
std::deque node$endgroup$
– miscco
yesterday
$begingroup$
@Ali Regarding your first comment, you will most likely never get rid of all allocations, as the std array is allocated into a container node anyway. In fact it even better to allocate a potentially smaller string than always putting a gargantuan array into
std::deque node$endgroup$
– miscco
yesterday
|
show 3 more comments
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216097%2fsimple-raw-buffer-queue-implementation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown