这是实现在C界缓冲区++以正确的方式[关闭](Is this a correct way to im

2019-08-19 08:02发布

我工作的一个程序,多线程访问,沉积在,并从有界缓冲容器退出交易。 我注意到与线程的一些主要问题,并怀疑我的缓冲部分或根本不正确的地方。

为了确保我知道我这个做的,我希望有我的缓冲代码看了过来。 这个类使用一个信号量,我在其他地方实现,我将承担工程现在(如果没有,我会找出答案很快!)我也补充说,试图解释我的推理意见。

首先,.h文件:

#ifndef BOUNDED_BUFFER_H
#define BOUNDED_BUFFER_H

#include "Semaphore.H"
#include <string> 
#include <vector>  

using namespace std; 

class Item{ //supposed to eventually be more extensible...seems silly with just a string for now

  public:
    Item(string _content){content = _content;} 
    string GetContent() {return content;}     

  private:  
};   

    class BoundedBuffer{

      public:
        BoundedBuffer(); 

        void Deposit(Item* _item); 
        Item* Retrieve();        
        int GetNumItems() {return count;} 
        vector<Item*> GetBuffer() {return buffer;} 
        void SetSize(int _size){
          capacity = _size;
          buffer.reserve(_size);  //or do I need to call "resize" 
        }  

      private:
        int capacity; 
        vector<Item*> buffer; //I originally wanted to use an array but had trouble with  
                              //initilization/sizing, etc. 
        int nextin; 
            int nextout; 
            int count; 

            Semaphore notfull;   //wait on this one before depositing an item
            Semaphore notempty;  //wait on this one before retrieving an item
        };

    #endif

接下来,在.cpp:

#include "BoundedBuffer.H"
#include <iostream>

using namespace std; 

BoundedBuffer::BoundedBuffer(){

  notfull.SetValue(0); 
  notempty.SetValue(0); 
  nextin = 0; 
  nextout = 0; 
  count = 0; 
}

void BoundedBuffer::Deposit(Item* _item){
  if(count == capacity){ 
    notfull.P(); //Cannot deposit into full buffer; wait
  }

  buffer[nextin] = _item; 
  nextin = (nextin + 1) % capacity;  //wrap-around
  count += 1;
  notempty.V();  //Signal that retrieval is safe 
}

Item* BoundedBuffer::Retrieve(){
  if(count == 0){
    notempty.P(); //cannot take from empty buffer; wait 
  }

  Item* x = buffer[nextout]; 
  nextout = (nextout + 1) % capacity;
  buffer.pop_back();  //or a different erase methodology? 
  count -= 1; 
  notfull.V(); //Signal that deposit is safe 
  return x; 
}

我认为,问题可能从我的选择载体的出现为基础容器(或者说,不正确的使用它),或者可能需要对安全性更阻挡机制(互斥锁等?)从外观上来看的事情,任何人都可以提供一些建议吗?

Answer 1:

这是一个非常普遍的问题(如何做一个适当的多线程队列)。 我以前见过的最好的答案就是这个堆栈溢出问题和这个网站 。 这些问题的答案是无界的队列,所以我将扩大和显示这里有界队列的答案。

你需要保护你的存款和检索功能互斥和使用条件变量做苏醒。

#include <mutex>
#include <condition_variable>

std::mutex the_mutex;
std::condition_variable the_notfull_cvar;
std::condition_variable the_notempty_cvar;

...

void BoundedBuffer::Deposit(Item* _item){
  std::unique_lock<std::mutex> lock(the_mutex);
  while ( /* buffer is full */ ){
    /* simultaneously wait and release the mutex */
    the_notfull_cvar.wait(lock);
    /* the mutex is reaquired at this point */
  }

  /* buffer has space and we own the mutex: insert the item */
  ...
  /* tell anyone waiting on an empty buffer that they can wake up. */
  the_notempty_cvar.notify_all();
}

Item* BoundedBuffer::Retrieve(){
  std::unique_lock<std::mutex> lock(the_mutex);
  while ( /* buffer is empty */ ){
    /* simultaneously wait and release the mutex */
    the_notempty_cvar.wait(lock);
    /* the mutex is reaquired at this point */
  }

  /* buffer has something in it and we own the mutex: get the item */
  ...
  /* tell anyone waiting on a full buffer that they can wake up. */
  the_notfull_cvar.notify_all();

  return x;
}

你GetNumItems()的GetBuffer()和的setSize()函数也需要与unique_locks保护。



Answer 2:

你看着提升:Circular_buffer ? 这是一个固定大小的存储领域,有一个标准库接口。 这可能会做你想做的,否则会给你一些指点。 循环缓冲区呢,如果你写的东西,当它是全覆盖的开始。 也许你不想,虽然是一个完整的()测试这样就可以避免在你的代码。



文章来源: Is this a correct way to implement a bounded buffer in C++ [closed]