Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: шаблоны класса ring_buffer, channel - гибкость или наоборот?
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
aliko
В scmrtos используются преимущества С++ в часнтости шаблоны.
например так объявляется шаблон класса кольцевого буфера
Код
template<typename T, uint16_t Size, typename S = uint8_t>
class ring_buffer

аналогично объявляется шаблон класса channel

С одной стороны вроде гибко но с другой...
если у меня есть несколько каналов или кольцевых буферов хранящих тип int но разной длины, то эти каналы уже совершенно разные типы данных, которые нельзя никак объединить, сделать, например, массив указателей на каналы разной длины или нельзя сделать класс включающий указатель на кольцевой буфер заранее не указав длины этого буфера. В итоге вместо гибкости получаем противоположный эффект.

Может есть какое-о просто решение о котором я не знаю, подскажите товарищи!
Уж очень не хочется менять код ОС или дублировать то что там уже написано...
dxp
Цитата(aliko @ Jun 23 2011, 03:00) *
С одной стороны вроде гибко но с другой...
если у меня есть несколько каналов или кольцевых буферов хранящих тип int но разной длины, то эти каналы уже совершенно разные типы данных, которые нельзя никак объединить, сделать, например, массив указателей на каналы разной длины

Буфера разной длины - это разные типы, как ни крути. Если вы объявили int A[10]; и int B[20];, то это разные типы, хотя и похожие.

Цитата(aliko @ Jun 23 2011, 03:00) *
или нельзя сделать класс включающий указатель на кольцевой буфер заранее не указав длины этого буфера.

Тут не понял.

Цитата(aliko @ Jun 23 2011, 03:00) *
В итоге вместо гибкости получаем противоположный эффект.

Вопрос в том, что вы понимаете под гибкостью. С++ с помощью поддержки параметризованных типов предлагает автоматическую генерацию кода, который в противном случае пришлось бы писать вручную. Если вас не устраивает сгенерированный код, не используйте.

Цитата(aliko @ Jun 23 2011, 03:00) *
Может есть какое-о просто решение о котором я не знаю, подскажите товарищи!

На мой взгляд объективно пока в шаблонах кольцевого буфера и канала не хватает специализации для указателей - это так, потому что для очередей сообщений очень удобно использовать указатели. Пока руки не дошли. Надеюсь, в следующем релизе дойдут.

Цитата(aliko @ Jun 23 2011, 03:00) *
Уж очень не хочется менять код ОС или дублировать то что там уже написано...

Меняйте, не бойтесь. Если получите хорошее решение, аффтары с радостью включат его в ближайший релиз, чтобы все желающие могли пользоваться результатами прогресса. Тем более, что сейчас там предусмотрен механизм расширения функциональности ОС с помощью специального интерфейса, не внося изменений в основной код и ничего не ломая.
aliko
Цитата
Буфера разной длины - это разные типы, как ни крути. Если вы объявили int A[10]; и int B[20];, то это разные типы, хотя и похожие.

Однако оба эти типа можно привести к int* и использовать этот указатель и для одного и для другого, сделать массив 2х указателей где первый из них будет указывать на А, второй на В.
Или например сделать класс членом которого является int* и тогда в одном экземпляре класса держать ссылку на А, в другом на В (это я и имел ввиду говоря о классе).
Однако как аналогичным образом организовать работу с ring_buffer разной длины? Все они - разные типы и как сделать указатель который мог бы указывать и на один и на другой (чтобы по-возможности как-нибудь без void*).

Цитата
На мой взгляд объективно пока в шаблонах кольцевого буфера и канала не хватает специализации для указателей - это так, потому что для очередей сообщений очень удобно использовать указатели. Пока руки не дошли. Надеюсь, в следующем релизе дойдут.

А тут можно чуточку поподробнее? Что значит специализация для указателей?
aliko
Вобщем вроде как-то так все решается:
Код
usr::ring_buffer<int, 20> ring1;
typedef usr::ring_buffer<int, 1> * ring_ptr;

int _tmain(int argc, _TCHAR* argv[])
{
    ring_ptr pring = reinterpret_cast<ring_ptr>(&ring1);
    ring1.push(1);
    ring1.push(2);
    pring->push(3);
    std::cout << int(pring->get_count()) << std::endl;
    std::cout << pring->pop() << "\t" << pring->pop_back() << std::endl;
    std::cout << int(pring->get_count()) << std::endl;
    return 0;
}


Вывод:
Цитата
3
1 3
1
Для продолжения нажмите любую клавишу . . .


Проверялось в MS Visual C++ 2010.
Было замечено следующее.
если тип указателя задан как
Код
typedef usr::ring_buffer<int, 1> * ring_ptr;

то при попытке положить второй элемент в буфер используя указатель
Код
pring->push(2);

ничего туда не ложится. Именно ВТОРОЙ элемент (при размере буфера указателя 1) должен быть положен напрямую через
Код
ring1.push(2);

а не через указатель, остальные же элементы можно ложить как угодно, хоть напрямую хоть через указатель.

чтобы это обойти надо задать тип указателя как-нибудь так
Код
typedef usr::ring_buffer<int, 100> * ring_ptr;

тоесть задать заведомо бОльший размер буфера у указателя

Вобщем всеравно какие-то костыли получаются...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.