I want to set a limit on my Queue. You can find below the implementation of the Queue class.
So, in short, I want to write in Queue in one thread until the limit and then wait for the free space. And the second thread read the Queue and do some operations with the data that it received.
int main()
{
//loop that adds new elements to the Queue.
thread one(buildQueue, input, Queue);
loop{
obj = Queue.pop()
func(obj) //do some math
}
}
So the problems is that the Queue builds until the end, but I want to set only 10 elements, for example. And program should work like this:
Check whether free space in Queue is available.
If there is no space - wait.
Write in the Queue until the limit.
Class Queue
template <typename T> class Queue{
private:
const unsigned int MAX = 5;
std::deque<T> newQueue;
std::mutex d_mutex;
std::condition_variable d_condition;
public:
void push(T const& value)
{
{
std::unique_lock<std::mutex> lock(this->d_mutex);
newQueue.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->newQueue.empty(); });
T rc(std::move(this->newQueue.back()));
this->newQueue.pop_back();
return rc;
}
unsigned int size()
{
return newQueue.size();
}
unsigned int maxQueueSize()
{
return this->MAX;
}
};
I'm pretty new in threads program so that I could misunderstand the conception. That is why different hints are highly appreciated.
You should have researched the Queue class in the MSDN website. It provides extensive information revolving methods included with Queue. However, to answer your question specifically, to set a queue with a specific capacity, it would be the following:
Queue(int capacity)
where it is Type System::int32 capacity is the initial number of elements in the queue. Then, your queue will be filled until the limit. The issue is, the queue will not "stop" once its filled. It will start to allocate more memory as that is its nature so in your threaded (or multithreaded by the sounds of it), you must make sure to take care of the realoc-deallocation of the queue memory based on timing. You should be able to determine the milliseconds needed to fill your queue with the desired capacity and read the queue, meanwhile clearing the queue. Likewise, you can copy the queue contents to a 1D array and do a full queue clear using MyQueue->Clear()without having to read queue elements 1 by one (if timing and code complexity is an issue).
Related
I have to program a multiple producer-consumer system in C++, but I'm lost trying to put together each part of the model (threads with its correct buffer). The basic functioning of the model is: I have an initial thread that executes a function. This returned results need to be put in an undetermined number of buffers, because each elements that the function proccess is different and it needs to be treated in a single thread. Then, with the data stored in the buffers, another n threads need to get the data of this buffers to do another function, and the return of this need to be put in some buffers again.
At the moment I have got this buffer structure created:
template <typename T>
class buffer {
public:
atomic_buffer(int n);
int bufSize() const noexcept;
bool bufEmpty() const noexcept;
bool full() const noexcept;
~atomic_buffer() = default;
void put(const T & x, bool last) noexcept;
std::pair<bool,T> get() noexcept;
private:
int next_pos(int p) const noexcept;
private:
struct item {
bool last;
T value;
};
const int size_;
std::unique_ptr<item[]> buf_;
alignas(64) std::atomic<int> nextRd_ {0};
alignas(64) std::atomic<int> nextWrt_ {0};
};
I've also created a vectorstructure which stores a collection un buffers, in order to satisfy the undetermined number of threads necessity.
std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;
for(int i=0; i<n; i++){
v1.push_back(std::unique_ptr<locked_buffer<std::pair<int,std::vector<std::vector<unsigned char>>>>> (new locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>(aux)));
}
Edit:
Without knowing more context, this looks like an application for a standard thread pool. You have different tasks that are enqueued to a synchronized queue (like the buffer class you have there). Each worker thread of the thread pool polls this queue and processes one task each time (by executing a run() method for example). They write the results back into another synchronized queue.
Each worker thread has an own thread-local pair of input and output buffers. They don't need synchronization because they are only accessed from within the owner thread itself.
Edit: Actually, I think this can be simplified a lot: Just use a thread pool and one synchronized queue. The worker threads can enqueue new tasks directly into the queue. Each of your threads in the drawing would correspond to one type of task and implement a common Task interface.
You don't need mutiple buffers. You can use polymorphism and put everything in one buffer.
Edit 2 - Explanation of thread pools:
A thread pool is just a concept. Forget about the pooling aspect, use a fixed number of threads. The main idea is: Instead of having several threads with a specific function, have N threads that can process any kind of task. Where N is the number of cores of the CPU.
You can transform this
into
The worker thread does something like the following. Note that this is simplified, but you should get the idea.
void Thread::run(buffer<Task*>& queue) {
while(true) {
Task* task = queue.get();
if(task)
task->execute();
while(queue.isEmpty())
waitUntilQueueHasElement();
}
}
And your tasks implement a common interface so you can put Task* pointers into a single queue:
struct Task {
virtual void execute() = 0;
}
struct Task1 : public Task {
virtual void execute() override {
A();
B1();
C();
}
}
...
Also, do yourself a favour and use typedefs ;)
`std::vector<std::unique_ptr<locked_buffer<std::pair<int, std::vector<std::vector<unsigned char>>>>>> v1;`
becomes
typedef std::vector<std::vector<unsigned char>> vector2D_uchar;
typedef std::pair<int, vector2D_uchar> int_vec_pair;
typedef std::unique_ptr<locked_buffer<int_vec_pair>> locked_buffer_ptr;
std::vector<locked_buffer_ptr> v1;
I'm programming a lock-free single-consumer single-producer growable queue in C++ for a real-time system. The internal queue works but it needs to be growable. The producer thread is real-time thus any operation needs to be deterministic (so no waits, locks, memory allocations), while the consumer thread isn't.
Thus the idea is that the consumer thread occasionally grows the size of the queue if need be. The implementation of the queue is such that the consumer-end cannot grow. Therefore the actual queue is indirectly wrapped inside an object which dispatches calls, and the actual growth is implemented by swapping the reference to the internal queue to a new, while keeping the old one hanging around in case the producer thread is using it.
The problem however is, that I cannot figure out how to prove when the producer thread stops using the old queue and it therefore is safe to delete without having to resort to locks. Here is a pseudo-representation of the code:
template<typename T>
class queue
{
public:
queue()
: old(nullptr)
{
current.store(nullptr);
grow();
}
bool produce(const T & data)
{
qimpl * q = current.load();
return q->produce(data);
}
bool consume(T & data)
{
// the queue has grown? if so, a new and an old queue exists. consume the old firstly.
if (old)
{
// here is the problem. we never really know when the producer thread stops using
// the old queue and starts using the new. it could be concurrently halfway-through inserting items
// now, while the following consume call fails meanwhile.
// thus, it is not safe yet to delete the old queue.
// we know however, that it will take at most one call to produce() after we called grow()
// before the producer thread starts using the new queue.
if (old->consume(data))
{
return true;
}
else
{
delete old;
old = nullptr;
}
}
if (current.load()->consume(data))
{
return true;
}
return false;
}
// consumer only as well
void grow()
{
old = current.load();
current.store(new qimlp());
}
private:
class qimpl
{
public:
bool produce(const T & data);
bool consume(const T & data);
};
std::atomic<qimpl *> current;
qimpl * old;
};
Note that ATOMIC_POINTER_LOCK_FREE == 2 is a condition for the code to compile. The only provable condition I see, is, that if grow() is called, the next produce() call will use the new internal queue. Thus if an atomic count inside produce is incremented each call, then its safe to delete the old queue at N + 1, where N is the count at the time of the grow() call. The issue, however, is that you then need to atomically swap the new pointer and store the count which seems not possible.
Any ideas is welcome, and for reference, this is how the system would work:
queue<int> q;
void consumer()
{
while (true)
{
int data;
if (q.consume(data))
{
// ..
}
}
}
void producer()
{
while (true)
{
q.produce(std::rand());
}
}
int main()
{
std::thread p(producer); std::thread c(consumer);
p.detach(); c.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
EDIT:
Okay, the problem is solved now. It dawned on me, that the old queue is provably outdated when an item is pushed to the new queue. Thus the snippet now looks like this:
bool pop(T & data)
{
if (old)
{
if (old->consume(data))
{
return true;
}
}
// note that if the old queue is empty, and the new has an enqueued element, we can conclusively
// prove that it is safe to delete the old queue since it is (a) empty and (b) the thread state
// for the producer is updated such that it uses all the new entities and will never use the old again.
// if we successfully dequeue an element, we can delete the old (if it exists).
if (current.load()->consume(data))
{
if (old)
{
delete old;
old = nullptr;
}
return true;
}
return false;
}
I don't fully understand the usage of grow() in your algorithm, but it seems you need some sort of Read-Copy-Update (RCU) mechanism for safetly deleting queue when it is not needed.
This article describes different flavors of this mechanism related to Linux, but you can google RCU flavors, suitable for other platforms.
The goal is to have a writer thread and a reader thread but only the writer news and deletes the action object. There is only one reader and one writer.
something like:
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
// returns used Object to be deleted or 0 if none exist
T * push(T * added); // added will be processed by reader
// blocks if there are no objects in queue
// returns item pushed from writer for deletion
T * pop(T * used); // used will be freed by writer
private:
// stuff here
};
-or better if the delete and return can be encapsulated:
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
push(T * added); // added will be processed by reader
// blocks if there are no objects in queue
// returns item pushed from writer for deletion
T& pop();
private:
// stuff here
};
where the writer thread has a loop like:
my_object *action;
while (1) {
// create action
delete my_queue.push(action);
}
and the reader has a loop like:
my_object * action=0;
while(1) {
action=my_queue.pop(action);
// do stuff with action
}
The reason to have the writer delete the action item is for performance
Is there an optimal way to do this?
Bonus points if MAX=0 is specialized to be unbounded (not required, just tidy)
I'm not looking for the full code, just the data structure and general approach
This is an instance of the producer-consumer problem. A popular way to solve this is to use a lockfree queue.
Also, the first practical change you might want to make is to add a sleep(0) into the production/consumption loops, so you will give up your time slice every iteration and won't end up using 100% of a CPU core.
The most common solution to this problem is to pass values, not pointers.
You can pass shared_ptr to this queue. Your queue doesn't need to know how to free memory after you.
If you use something like Lamport's ring buffer for single producer - single consumer blocking queue, it's a natural solution to use std::vector under the hood that will call destructors for every element automatically.
template<typename T, std::size_t MAX>
class TSQ
{
public:
// blocks if there are MAX items in queue
void push(T added); // added will be processed by reader
// blocks if there are no objects in queue
T pop();
private:
std::vector<T> _content;
size_t _push_index;
size_t _pop_index;
...
};
I had a need for a Blocking Queue in C++ with timeout-capable offer(). The queue is intended for multiple producers, one consumer. Back when I was implementing, I didn't find any good existing queues that fit this need, so I coded it myself.
I'm seeing segfaults come out of the take() method on the queue, but they are intermittent. I've been looking over the code for issues but I'm not seeing anything that looks problematic.
I'm wondering if:
There is an existing library that does this reliably that I should
use (boost or header-only preferred).
Anyone sees any obvious flaw in my code that I need to fix.
Here is the header:
class BlockingQueue
{
public:
BlockingQueue(unsigned int capacity) : capacity(capacity) { };
bool offer(const MyType & myType, unsigned int timeoutMillis);
MyType take();
void put(const MyType & myType);
unsigned int getCapacity();
unsigned int getCount();
private:
std::deque<MyType> queue;
unsigned int capacity;
};
And the relevant implementations:
boost::condition_variable cond;
boost::mutex mut;
bool BlockingQueue::offer(const MyType & myType, unsigned int timeoutMillis)
{
Timer timer;
// boost::unique_lock is a scoped lock - its destructor will call unlock().
// So no need for us to make that call here.
boost::unique_lock<boost::mutex> lock(mut);
// We use a while loop here because the monitor may have woken up because
// another producer did a PulseAll. In that case, the queue may not have
// room, so we need to re-check and re-wait if that is the case.
// We use an external stopwatch to stop the madness if we have taken too long.
while (queue.size() >= this->capacity)
{
int monitorTimeout = timeoutMillis - ((unsigned int) timer.getElapsedMilliSeconds());
if (monitorTimeout <= 0)
{
return false;
}
if (!cond.timed_wait(lock, boost::posix_time::milliseconds(timeoutMillis)))
{
return false;
}
}
cond.notify_all();
queue.push_back(myType);
return true;
}
void BlockingQueue::put(const MyType & myType)
{
// boost::unique_lock is a scoped lock - its destructor will call unlock().
// So no need for us to make that call here.
boost::unique_lock<boost::mutex> lock(mut);
// We use a while loop here because the monitor may have woken up because
// another producer did a PulseAll. In that case, the queue may not have
// room, so we need to re-check and re-wait if that is the case.
// We use an external stopwatch to stop the madness if we have taken too long.
while (queue.size() >= this->capacity)
{
cond.wait(lock);
}
cond.notify_all();
queue.push_back(myType);
}
MyType BlockingQueue::take()
{
// boost::unique_lock is a scoped lock - its destructor will call unlock().
// So no need for us to make that call here.
boost::unique_lock<boost::mutex> lock(mut);
while (queue.size() == 0)
{
cond.wait(lock);
}
cond.notify_one();
MyType myType = this->queue.front();
this->queue.pop_front();
return myType;
}
unsigned int BlockingQueue::getCapacity()
{
return this->capacity;
}
unsigned int BlockingQueue::getCount()
{
return this->queue.size();
}
And yes, I didn't implement the class using templates - that is next on the list :)
Any help is greatly appreciated. Threading issues can be really hard to pin down.
-Ben
Why are cond, and mut globals? I would expect them to be members of your BlockingQueue object. I don't know what else is touching those things, but there may be an issue there.
I too have implemented a ThreadSafeQueue as part of a larger project:
https://github.com/cdesjardins/QueuePtr/blob/master/include/ThreadSafeQueue.h
It is a similar concept to yours, except the enqueue (aka offer) functions are non-blocking because there is basically no max capacity. To enforce a capacity I typically have a pool with N buffers added at system init time, and a Queue for message passing at run time, this also eliminates the need for memory allocation at run time which I consider to be a good thing (I typically work on embedded applications).
The only difference between a pool, and a queue is that a pool gets a bunch of buffers enqueued at system init time. So you have something like this:
ThreadSafeQueue<BufferDataType*> pool;
ThreadSafeQueue<BufferDataType*> queue;
void init()
{
for (int i = 0; i < NUM_BUFS; i++)
{
pool.enqueue(new BufferDataType);
}
}
Then when you want send a message you do something like the following:
void producerA()
{
BufferDataType *buf;
if (pool.waitDequeue(buf, timeout) == true)
{
initBufWithMyData(buf);
queue.enqueue(buf);
}
}
This way the enqueue function is quick and easy, but if the pool is empty, then you will block until someone puts a buffer back into the pool. The idea being that some other thread will be blocking on the queue and will return buffers to the pool when they have been processed as follows:
void consumer()
{
BufferDataType *buf;
if (queue.waitDequeue(buf, timeout) == true)
{
processBufferData(buf);
pool.enqueue(buf);
}
}
Anyways take a look at it, maybe it will help.
I suppose the problem in your code is modifying the deque by several threads. Look:
you're waiting for codition from another thread;
and then immediately sending a signal to other threads that deque is unlocked just before you want to modify it;
then you modifying the deque while other threads are thinking deque is allready unlocked and starting doing the same.
So, try to place all the cond.notify_*() after modifying the deque. I.e.:
void BlockingQueue::put(const MyType & myType)
{
boost::unique_lock<boost::mutex> lock(mut);
while (queue.size() >= this->capacity)
{
cond.wait(lock);
}
queue.push_back(myType); // <- modify first
cond.notify_all(); // <- then say to others that deque is free
}
For better understanding I suggest to read about the pthread_cond_wait().
This is a classic c/p problem where some threads produce data while other read the data. Both the producer and consumers are sharing a const sized buffer. If the buffer is empty then the consumers have to wait and if it is full then the producer has to wait. I am using semaphores to keep track of full or empty queues. The producer is going to decrement free spots semaphore, add value, and increment filled slots semaphore. So I am trying to implement a program that gets some numbers from the generator function, and then prints out the average of the numbers. By treating this as a producer-consumer problem, I am trying to save some time in the execution of the program. The generateNumber function causes some delay in the process so I want to create a number of threads that generate numbers, and put them into a queue. Then the "main thread" which is running the main function has to read from the queue and find the sum and then average. So here is what I have so far:
#include <cstdio>
#include <cstdlib>
#include <time.h>
#include "Thread.h"
#include <queue>
int generateNumber() {
int delayms = rand() / (float) RAND_MAX * 400.f + 200;
int result = rand() / (float) RAND_MAX * 20;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = delayms * 1000000;
nanosleep(&ts, NULL);
return result; }
struct threadarg {
Semaphore filled(0);
Semaphore empty(n);
std::queue<int> q; };
void* threadfunc(void *arg) {
threadarg *targp = (threadarg *) arg;
threadarg &targ = *targp;
while (targ.empty.value() != 0) {
int val = generateNumber();
targ.empty.dec();
q.push_back(val);
targ.filled.inc(); }
}
int main(int argc, char **argv) {
Thread consumer, producer;
// read the command line arguments
if (argc != 2) {
printf("usage: %s [nums to average]\n", argv[0]);
exit(1); }
int n = atoi(argv[1]);
// Seed random number generator
srand(time(NULL));
}
I am a bit confused now because I am not sure how to create multiple producer threads that are generating numbers (if q is not full) while the consumer is reading from the queue (that is if q is not empty). I am not sure what to put in the main to implment it.
also in "Thread.h", you can create a thread, a mutex, or a semaphore. The thread has the methods .run(threadFunc, arg), .join(), etc. A mutex can be locked or unlocked. The semaphore methods have all been used in my code.
Your queue is not synchronized, so multiple producers could call push_back at the same time, or at the same time the consumer is calling pop_front ... this will break.
The simple approach to making this work is to use a thread-safe queue, which can be a wrapper around the std::queue you already have, plus a mutex.
You can start by adding a mutex, and locking/unlocking it around each call you forward to std::queue - for a single consumer that should be sufficient, for multiple consumers you'd need to fuse front() and pop_front() into a single synchronized call.
To let the consumer block while the queue is empty, you can add a condition variable to your wrapper.
That should be enough that you can find the answer online - sample code below.
template <typename T> class SynchronizedQueue
{
std::queue<T> queue_;
std::mutex mutex_;
std::condition_variable condvar_;
typedef std::lock_guard<std::mutex> lock;
typedef std::unique_lock<std::mutex> ulock;
public:
void push(T const &val)
{
lock l(mutex_); // prevents multiple pushes corrupting queue_
bool wake = queue_.empty(); // we may need to wake consumer
queue_.push(val);
if (wake) condvar_.notify_one();
}
T pop()
{
ulock u(mutex_);
while (queue_.empty())
condvar_.wait(u);
// now queue_ is non-empty and we still have the lock
T retval = queue_.front();
queue_.pop();
return retval;
}
};
Replace std::mutex et al with whatever primitives your "Thread.h" gives you.
What I would do is this:
Make a data class that hides your queue
Create thread-safe accessor methods for saving a piece of data to the q, and removing a piece of data from the q ( I would use a single mutex, or a critical section for accessors)
Handle the case where a consumor doesn't have any data to work with (sleep)
Handle the case where the q is becoming too full, and the producers need to slow down
Let the threads go willy-nilly adding and removing as they produce / consume
Also, remember to add a sleep into each and every thread, or else you'll peg the CPU and not give the thread scheduler a good spot to switch contexts and share the CPU with other threads / processes. You don't need to, but it's a good practice.
When managing shared state like this, you need a condition variable and
a mutex. The basic pattern is a function along the lines of:
ScopedLock l( theMutex );
while ( !conditionMet ) {
theCondition.wait( theMutex );
}
doWhatever();
theCondition.notify();
In your case, I'd probably make the condition variable and the mutex
members of the class implementing the queue. To write, the
conditionMet would be !queue.full(), so you'd end up with something
like:
ScopedLock l( queue.myMutex );
while ( queue.full() ) {
queue.myCondition.wait();
}
queue.insert( whatever );
queue.myCondition.notify();
and to read:
ScopedLock l( queue.myMutex );
while ( queue.empty() ) {
queue.myCondition.wait();
}
results = queue.extract();
queue.myCondition.notify();
return results;
Depending on the threading interface, there may be two notify
functions: notify one (which wakes up a single thread), and notify all
(which wakes up all of the waiting threads); in this case, you'll need
notify all (or you'll need two condition variables, one for space to
write, and one for something to read, with each function waiting on one,
but notifying the other).
Protect the queue accesses with a mutex, that should be it. A 'Computer Science 101' bounded producer-consumer queue needs two semaphores, (to manage the free/empty count and for producers/consumers to wait on, as you are already doing), and one mutex/futex/criticalSection to protect the queue.
I don't see how replacing the semaphores and mutex with condvars is any great help. What's the point? How do you implement a bounded producer-consumer queue with condvars that works on all platforms with multiple producers/consumers?
#include<iostream>
#include<deque>
#include<mutex>
#include<chrono>
#include<condition_variable>
#include<thread>
using namespace std;
mutex mu,c_out;
condition_variable cv;
class Buffer
{
public:
Buffer() {}
void add(int ele)
{
unique_lock<mutex> ulock(mu);
cv.wait(ulock,[this](){return q.size()<_size;});
q.push_back(ele);
mu.unlock();
cv.notify_all();
return;
}
int remove()
{
unique_lock<mutex> ulock(mu);
cv.wait(ulock,[this](){return q.size()>0;});
int v=q.back();
q.pop_back();
mu.unlock();
cv.notify_all();
return v;
}
int calculateAvarage()
{
int total=0;
unique_lock<mutex> ulock(mu);
cv.wait(ulock,[this](){return q.size()>0;});
deque<int>::iterator it = q.begin();
while (it != q.end())
{
total += *it;
std::cout << ' ' << *it++;
}
return total/q.size();
}
private:
deque<int> q;
const unsigned int _size=10;
};
class Producer
{
public:
Producer(Buffer *_bf=NULL)
{
this->bf=_bf;
}
void Produce()
{
while(true)
{
int num=rand()%10;
bf->add(num);
c_out.lock();
cout<<"Produced:"<<num<<"avarage:"<<bf->calculateAvarage()<<endl;
this_thread::sleep_for(chrono::microseconds(5000));
c_out.unlock();
}
}
private:
Buffer *bf;
};
class Consumer
{
public:
Consumer(Buffer *_bf=NULL)
{
this->bf=_bf;
}
void Consume()
{
while (true)
{
int num=bf->remove();
c_out.lock();
cout<<"Consumed:"<<num<<"avarage:"<<bf->calculateAvarage()<<endl;
this_thread::sleep_for(chrono::milliseconds(5000));
c_out.unlock();
}
}
private:
Buffer *bf;
};
int main()
{
Buffer b;
Consumer c(&b);
Producer p(&b);
thread th1(&Producer::Produce,&p);
thread th2(&Consumer::Consume,&c);
th1.join();
th2.join();
return 0;
}
Buffer class has doublended queue and max Buffer size of 10.
It has two function to add into queue and remove from queue.
Buffer class has calculateAvarage() function which will calculate the avarage echa time a element is added or deleted.
There are two more classes one is producer and consumer having buffwr class pointer .
We are having Consume() in consumer class and Produce() in Producer class.
Consume()>>Lock the buffer and check if size is of buffer is not 0 it will remove from Buffer and notify to producer and unlock.
Produce()>>Lok the buffer and check if size is of buffer is not max buffer size it will add and notify to consumer and unlock.