2013-05-31 5 views
1

я хочу использовать boost::atomic для ожидания свободного кольцевого буфера, как описано здесь:Повысьте атомные: ждать свободного кольцевой буфер с большим объемом данных

Boost Example

Моих producer обеспечивает большой объем данных на то же время (unsigned char, + - 3000 значений), точно так же, как матрица, она будет заполняться по строкам. Каков наилучший способ для push этих значений в буфере? Должен ли я просто контактировать с ними или могу ли я memcpy их внутри каким-то образом?

То же самое касается pop, если я хочу прочитать кучу значений в то же время ...


Вот что я придумал, какой-либо причине это не должно быть хорошо? Мне просто нужно убедиться, что RINGBUFFERSIZE % iSize = 0.

#define RINGBUFFERSIZE = 30000 

ring_[RINGBUFFERSIZE]; 

bool push(unsigned char* iData, int iSize) 
{ 
    size_t head = head_.load(boost::memory_order_relaxed); 
    size_t next_head = next(head,iSize); 
    if (next_head == tail_.load(boost::memory_order_acquire)) 
    return false; 
    memcpy(ring_+head,iData,iSize); 
    head_.store(next_head, boost::memory_order_release); 
} 

bool pop(unsigned char * value, int iSize) 
{ 
    size_t tail = tail_.load(boost::memory_order_relaxed); 
    if (tail == head_.load(boost::memory_order_acquire)) 
     return false; 
    value = &ring_[tail]; 
    tail_.store(next(tail,iSize), boost::memory_order_release); 
    return true; 
} 


size_t next(size_t current, int iSize) 
{ 
    return (current + iSize) % RINGBUFFERSIZE; 
} 
+0

Предлагаемое решение не совсем работает, потому что 'next_head' может быть завернуто. В этом случае у вас нет смежного блока и вы не можете сделать ни одного «memcpy» (конечно, вы можете проверить этот случай и, возможно, сделать два). – Useless

ответ

1

Самый быстрый способ подтолкнуть указатель (либо unsigned char * или указатель на какой-либо структуры, которая содержит длину, а).

Конечно, предполагая, что это нормально, чтобы заставить точно те же куски, которые были нажаты, это просто переводит проблему: теперь вам нужно как-то управлять распределением этих буферов.


Простое решение образец для управления ломти:

  1. предварительно выделить «достаточное количество» объектов порций фиксированного размера (скажем, динамическая длина + unsigned char data[3096] или любой другой)
  2. отправить адрес куске в вашем безжизненном кольцевом буфере
  3. отправить адрес назад в другом кольцевом буфере, когда потребитель выполнен с ним, поэтому производитель может перерабатывать один и тот же объект куска

Если вы действительно не можете сделать это, вы могли выбрать максимальный размер для ваших кусков и тяни/поп-объектов этого размера по стоимости ... но если честно это кажется очень расточительно (даже если объект знает свою длину, поэтому не должен memcpy весь массив 3k для небольших кусков).

+0

Точно, указанная память больше недействительна, поэтому мне нужно скопировать данные. – Smash

+0

Несомненно, вы контролируете действительность ваших буферов? – Useless

+0

Данные поступают из tcp-соединения, поэтому я должен хранить его каждый раз. – Smash