C++11 сделать свои итераторы begin() end()

10 000 руб. за проект • безналичный расчёт, электронные деньги
27 октября 2017, 17:29 • 1 отклик • 65 просмотров
Я не уверен можно ли такое сделать, но подозреваю что можно.

С++11, детали обсуждаемы.

1. Есть базовая структура-элемент
typedef struct {
unsigned num;
std::stri ng somedata;
char s[64];
unsigned flags;
unsigned time t;
} smart_t;

2. Я хочу ее разместить в кольцевом буфере на 10000 элементов (например)

3. Есть некий класс Smart, который внутри себя хранит какой-нибудь
std::vector <smart_t> data;
и имеет несколько методов, среди которых главный:
place (time, somedata);
он
помещает новые данные в кольцевой буфер на свободное место, если нет
свободного то затирает (на самом деле просто обновляет) самый старый
элемент и помещает на его место, num каждый раз при помещение нового
элемента увеличивается на единицу
он же возвращает ссылку на вставленный элемент
find(num) возвращает итератор на элемент по его номеру или на end()

4. Сейчас внутри Smart это реализовано через:
std::list <smart_t> data;
новые элементы добавляются через push_back, а старые удаляются при этом с его начала
еще этот Smart имеет методы begin() и end() которые просто транслируются сейчас в list

5. Соответственно я могу легко пробегать через всякие там удобные std::find_if (smart.begin(), smart.end() …)

6.
Из неудобств: только отсутствие многопоточности (без блокировок),
поскольку в какой-то момент begin() перестает быть валидным и указывает
черти куда (после вызова очередного place и затирания им же первого
элемента)
Поскольку вставки происходят около 50 раз в секунду, очень
много выделяется/освобождается памяти (хотя я не знаю как там
стандартная библиотека себе ведет, может резервирует что)

7. Я
хочу, чтобы все данные оставались всегда в одном участке памяти и никуда
не перемещались, а лишь только в какой-то момент могли быть затерты,
при обновлении покругу

8. Когда будет реализован этот кольцевой
буфер у нас будет внутри некий указатель, по которому мы знаем точку, в
которую будут записан следующий пакет данных при вызове очередного
place(), затем он будет смещен на единицу, а при достижении реальной
границы, этот указатель будет «прокручен» на начало реального кольцевого
буфера

9. Я бы хотел иметь ОСОБЕННЫЕ begin/end (в этом и
состоит задача), которые были бы как обычные итераторы, но они имели бы
возможность прокрутиться

я получил бы auto it = smart.begin();
потом я его прибавлял бы, пока он не дошел бы до реальной границы
кольцевого буфера, а при следующем инкременте он уже указывал бы на
начало этого кольцевого буфера, а для меня, как пользователя это было бы
абсолютно прозрачно

10. Аналогично rebegin/rend, чтобы можно
было пойти в обратно направлении, сначала обработать в цикле самый
свежий кусок данных и так постепенно двигаться в сторону самого старого

11.
При это может возникнуть такая ситуация, что за время проходя например
от rebegin к rend() ближе к rend() уже будут записаны обновленные
данные, меня это совершенно не смущает

12. Должно работать без блокировок, писать будет один поток, читать – много других, причем "читатели" обновляют информацию в структуре, все кроме поля num, по поводу "синхронизации читателей" не стоит беспокоиться, это отдельная история

13. end() выходит, что может постоянно уползать (сдвигаться)