带有线程向量和队列的管道C ++

时间:2016-05-09 11:32:24

标签: c++ vector thread-safety queue pipeline

这是我的代码,它可以工作,但经过几次迭代后,它会停止而没有任何错误,可能是因为某些种族或死锁。

代码的目标是为编码应用程序建模:在创建一些伪随机帧之后,我的管道的各个阶段首先给出帧的类型,然后用一些随机操作对其进行编码。

为了做到这一点,我使用了两个不同的线程向量(每个阶段一个)与一些共享队列同时使用,一旦一个线程推送了一个帧,它被另一个向量中的另一个弹出,并被“编码”

 #include <iostream>
 #include <vector>
 #include <algorithm>

 #include "SafeQueue.h"

 using namespace std;

 const int DATA_MAG = 256;

 struct Frame
 {
    int num;

    char type;

    bool encoded;

    vector<vector<int>> grid;
};

void do_join(thread& t)
{
    t.join();
}

void join_all(vector<thread>& v)
{
    for_each(v.begin(),v.end(),do_join);
}

void create_input (Queue<Frame>& stream, int num_frames, int height, int width)
{
    for (int i = 0; i < num_frames; i++)
    {
        vector<vector<int>>tmp_grid(height, vector<int>(width, 0));

        Frame frame;

        for (int j = 0; j < height; j++)
        {
            for (int k = 0; k < width; k++)
            {
                tmp_grid[j][k] = rand()%DATA_MAG;
            }
        }

        frame.grid = tmp_grid;
        frame.num = i;

        stream.push(frame);
    }
}


void decide_type(int preset, Queue<Frame>& stream, Queue<Frame>& typed, vector<char>& param, int num_frames)
{
    cout<<"hello from decide"<<" "<<endl;

    for(int i = 0; i < num_frames; i++)
    {
        Frame tmp = stream.pop();

        int j = rand() % 10;

        if(j < preset)
        {
            tmp.type = 'I';
        }

        else
        {
            tmp.type = 'B';
        }

        param[tmp.num] = tmp.type;

        typed.push(tmp);
    }
}

void decode_flow(int preset, Queue<Frame>& typed, vector<Frame>& encoded,
                    vector<char>& parameters, int num_frames, int height, int width)
{
    cout<<"hello from decode"<<" "<<endl;

    for(int i = 0; i < num_frames; i++)
    {
        Frame f = typed.pop();

        if (f.type == 'I')
        {
            cout<<"hi from I"<<" "<<endl;
            for (int j = 0; j < height; j++)
            {
                for (int k = 0; k < width; k++)
                {
                    f.grid[j][k] = f.grid[j][k] * 2;
                }
            }
        }

        else cout<<"hi from B"<<" "<<endl;

        encoded.push_back(f);
    }
}




int main()
{
    srand(time(NULL));

    int num_threadsXstage = 2;

    int width = 500;
    int height = 500;

    int num_frames = 100;

    int frames_thread = num_frames/num_threadsXstage;

    int preset = 3;

    vector<Frame> final;

    //Vectors of threads
    vector<thread> typer;
    vector<thread> encoder;

    //Vector of parameters
    vector<char> parameters(num_frames);

    //Working queues
    Queue<Frame> created;
    Queue<Frame> typed;

    //Final vector
    vector<Frame> encoded(num_frames);

    //Movie creation

    create_input(created, num_frames, height, width);



for (int i = 0; i < num_threadsXstage; i++)
    {
        //stage 1
        typer.push_back(thread(bind(&decide_type, preset, ref(created),
                                    ref(typed), ref(parameters), frames_thread)));

        //stage 2
        encoder.push_back(thread(bind(&decode_flow, preset, ref(typed), ref(encoded),
                                      ref(parameters), frames_thread, height, width)));
    }


    // JOIN

    join_all(typer);

    join_all(encoder);


    for (int i = 0; i < num_frames; i++)
    {
        Frame k = typed.pop();

        cout<<k.type<<" ";
    }

    cout<<endl<<endl;

    for (int i = 0; i < num_frames; i++)
    {
        cout<<parameters[i]<<" ";
    }
}

这是我的线程安全队列的代码,或者至少应该是。

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

using namespace std;

template <typename T>

class Queue
{
private:
    queue<T> queue_;
    mutex mutex_;
    condition_variable cond_;

public:

    T pop()
    {
        unique_lock<std::mutex> mlock(mutex_);
        while (queue_.empty())
        {
            cond_.wait(mlock);
        }

        auto val = queue_.front();
        queue_.pop();
        return val;
    }

    void pop(T& item)
    {
        unique_lock<std::mutex> mlock(mutex_);

        while (queue_.empty())
        {
            cond_.wait(mlock);
        }
        item = queue_.front();
        queue_.pop();
    }

    void push(const T& item)
    {
        unique_lock<std::mutex> mlock(mutex_);
        queue_.push(item);
        mlock.unlock();
        cond_.notify_one();
    }
    Queue()=default;
    Queue(const Queue&) = delete;            // disable copying
    Queue& operator=(const Queue&) = delete; // disable assignment

};

1 个答案:

答案 0 :(得分:2)

在所有线程完成后,您从typed队列中提取所有排队的帧 - 但这是处理阶段之间的中间队列,现在是空的。对typed.pop()的调用将永久阻止。

您应该从输出队列encoded中提取帧。