cameron314 / cameron314/concurrentqueue
possible race condtion in accessing object in shared_ptr if share_ptr is the template type for concurrentqueue?
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 12.5k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
I would like to know if below passing shared_ptr created potential race condtion,
#include <string>
#include <thread>
#include <memory>
#include <condition_variable>
#include <mutex>
#include <deque>
#include <iostream>
#include <vector>
#include "third_party/concurrentqueue.h"
struct Dummy {
std::string name_;
};
class Consumer {
public:
Consumer() {
is_running_ = true;
data_thread_ = std::unique_ptr<std::thread>(new std::thread(&Consumer::listening, this));
}
void push(std::shared_ptr<Dummy> frame)
{
nice_queue.enqueue(frame);
}
virtual void listening() {
while (is_running_) {
std::shared_ptr<Dummy> frame;
if (nice_queue.try_dequeue(frame)) {
std::cout << frame->name_ << std::endl; //<--- is here a possible race condition as there is no memory fence
}
}
}
std::unique_ptr<std::thread> data_thread_;
moodycamel::ConcurrentQueue<std::shared_ptr<Dummy>> nice_queue;
std::atomic<bool> is_running_;
};
class Producer {
public:
Producer(std::shared_ptr<Consumer> consumer)
:consumer_(consumer){}
void send(std::shared_ptr<Dummy> frame) {
consumer_->push(frame);
}
protected:
std::shared_ptr<Consumer> consumer_;
};
int main() {
std::shared_ptr<Consumer> consumer = std::make_shared<Consumer>();
Producer prod(consumer);
for(int i =0; i<100; i++){
auto item = std::make_shared<Dummy>();
item->name_ = std::to_string(i);
prod.send(item);
}
}
My question is as the code shows, the Producer send an item to Consumer to be processed in another thread, so two things happens strictly one after another, but due to there is no memory fence, is there a possibility that when Consumer proccess the item, it doesnt see the final version of the item, and thus have an undefined behaviour?
Another question is will the below code has race condition? as this time I am passing index of the vector through the queue.
class MultiThread {
public:
MultiThread()
:size_(100000), data_count_(0), data_list_(100000){
thread_send_ = std::unique_ptr<std::thread>(new std::thread(&MultiThread::write_tick, this));
}
void produce() {
while(1) {
int node = data_count_ % size_;
data_list_[node].name_=std::to_string(data_count_);
tick_queue_.enqueue(node);
++data_count_;
}
}
void write_tick()
{
while (1)
{
int node;
if (tick_queue_.try_dequeue(node)) {
std::cout << data_list_[node].name_ << std::endl; //<-----Race Condition herer?
}
}
}
std::unique_ptr<std::thread> thread_send_;
moodycamel::ConcurrentQueue<int> tick_queue_;
std::vector<Dummy> data_list_;
int data_count_;
const int size_;
};
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the two examples in the issue and read third_party/concurrentqueue.h, focusing on ConcurrentQueue's enqueue and try_dequeue entry points and their memory-ordering guarantees. Compare the shared_ptr handoff with the vector-index handoff, then verify the conclusions against the C++ memory model; done means a documented, reproducible answer identifying whether each access is safe or races.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100