Reputation: 119
I'm trying to write a simple program that creates and uses a certain number (variable - it is a parameter passed by command line) of blocking queues. To easily access them, I thought about creating a vector of queues.
I'm using g++-8 to compile the program. The queue I have is provided by my professor, so I can't make any changes in its code.
Here is the code I've developed:
blocking_queue.hpp
#ifndef SKYLINE_BLOCKING_QUEUE_HPP
#define SKYLINE_BLOCKING_QUEUE_HPP
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <vector>
#include <chrono>
#include <cstddef>
#include <math.h>
#include <string>
#include <thread>
using namespace std::literals::chrono_literals;
//
// needed a blocking queue
// here is a sample queue.
//
template <typename T>
class blocking_queue
{
private:
std::mutex d_mutex;
std::condition_variable d_condition;
std::deque<T> d_queue;
public:
blocking_queue(){}
void push(T const& value) {
{
std::unique_lock<std::mutex> lock(this->d_mutex);
d_queue.push_front(value);
}
this->d_condition.notify_one();
}
T pop() {
std::unique_lock<std::mutex> lock(this->d_mutex);
this->d_condition.wait(lock, [=]{return !this->d_queue.empty(); });
T rc(std::move(this->d_queue.back()));
this->d_queue.pop_back();
return rc;
}
bool is_empty() {
std::unique_lock<std::mutex> lock(this->d_mutex);
this->d_condition.wait(lock, [=]{return !this->d_queue.empty(); });
printf("ADDED A INT\n");
return false;
}
int size() {
std::unique_lock<std::mutex> lock(this->d_mutex);
return(d_queue.size());
}
};
#endif // SKYLINE_BLOCKING_QUEUE_HPP
test.cpp
int main(char argc, char* argv[]) {
nw = atoi(argv[0]);
vector<blocking_queue<int>> myVector;
for(int i = 0; i < nw; i++) {
myVector.emplace_back();
}
}
When I try to compile the program, g++ gives me the following error:
error: use of deleted function ‘blocking_queue<int>::blocking_queue(blocking_queue<int>&&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ./test.cpp:10:
./blocking_queue.hpp:28:7: note: ‘blocking_queue<int>::blocking_queue(blocking_queue<int>&&)’ is implicitly deleted because the default definition would be ill-formed:
class blocking_queue
^~~~~~~~~~~~~~
./blocking_queue.hpp:28:7: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/8/mutex:43,
from ./blocking_queue.hpp:9,
from ./test.cpp:10:
/usr/include/c++/8/bits/std_mutex.h:97:5: note: declared here
mutex(const mutex&) = delete;
^~~~~
In file included from ./test.cpp:10:
./blocking_queue.hpp:28:7: error: use of deleted function ‘std::condition_variable::condition_variable(const std::condition_variable&)’
class blocking_queue
^~~~~~~~~~~~~~
How can I solve the problem?
Upvotes: 1
Views: 187
Reputation: 2695
If you simply need to create a vector of nw
elements you can do the following:
std::vector<blocking_queue<int>> myVector(nw);
The use of emplace_back
could work, but when doing emplace_back
the vector
might need to resize and resize might trigger copies between old buffer and new buffer. See C++ vector emplace_back calls copy constructor . As far as I know if you have a noexcept
move ctor, the vector
will use it instead of copying but I do not know if this is a guaranteed optimization from the standard of something that an implementor could choose to do. Regardless, your class does not seem to be movable, because of some of its members, namely condition_variable
and mutex
.
So using this particular object inside a vector could be problematic, depends on your use case.
If you need to be able to resize your container you can:
vector
and use unique_ptr
of the queue
object to store elements inside the vectorstd::list
that should not require to copy objects when resizing because it is a linked list.In both cases you might lose performance
Upvotes: 3
Reputation: 20492
Try using emplace_back()
instead of push_back()
.
push_back()
uses the copy constructor, which seems to have been deleted.
Upvotes: 0