LINUX.ORG.RU

Сообщения maxis11

 

Не возникнет ли гонка данных?

Суть в том, что чтение из одного блока данных происходит очень часто из разных потоков, но в определенный момент один(заранее заданный поток) может обновить данные, так как код используется в очень критичном месте и обновление данных происходит очень быстро, никакой блокировки с засыпанием быть не должно (mutex, shared_mutex). Написал свой велосипед:

Сама структура:

struct BufferData {
  ...
  volatile std::atomic<bool> m_remapFlag{false}; //флаг, если происходит запись
  volatile std::atomic<std::size_t> m_usageCounter{0}; //количество чтений
};

Блокировка/освобождение на чтение (блокировка на чтение не должно блокировать другое чтение):

BufferData *OGLBuffer::lock() {
  std::shared_ptr<BufferData> ptr;
  if (!m_data.expired()) {
    ptr = m_data.lock();
  } else
    throw std::runtime_error("Buffer page deleted");
  //Ждем пока обновляют данные
  while (ptr->m_remapFlag) {
    continue;
  }
  //Увеличиваем счетчик
  ptr->m_usageCounter++;
  if (!ptr->m_remapFlag) {
    //Если за это время не начали обновлять данные то возвращаем указатель
    return ptr.get();
  } else {
    //Иначе повторяем попытку
    unlock();
    return lock();
  }

//Метод освобождения довольно прост
void OGLBuffer::unlock() { m_data.lock()->m_usageCounter--; }

Теперь блокировка/освобождение на запись:

void OGLPage::lockBuffer(std::size_t const &id) {
  m_buffers[id]->m_remapFlag = true; //Ставим флаг на запись
  //Ждем конца чтений
  while (m_buffers[id]->m_usageCounter > 0) {
    continue;
  }
}

void OGLPage::unlockBuffer(std::size_t const &id) {
  //Чистим флаг
  m_buffers[id]->m_remapFlag = false;
}

Вроде бы не вижу мест где гонка могла бы возникнуть, однако доказать что так и есть, увы, не могу. Хотелось бы услышать комментариев/критики по этому поводу.

 

maxis11
()

Шаблонный оператор + fold expression + variadic templates = ругается clang

Решил я поиграться с fold expression в c++1z, сделал шаблонный оператор, который объединяет два кортежа

template <class... Args1, class... Args2>
constexpr decltype(auto) operator+(const ::std::tuple<Args1...> &tup1,
                                   const ::std::tuple<Args2...> &tup2) {
   return ::std::tuple_cat(tup1, tup2);
}

template <class... Args1, class... Args2>
constexpr decltype(auto) operator+(::std::tuple<Args1...> &&tup1,
                                   ::std::tuple<Args2...> &&tup2) {
   return ::std::tuple_cat(tup1, tup2);
}

И вроде бы отлично работает для двух параметров

template <class Arg1, class Arg2>
constexpr decltype(auto) concat_test(Arg1 &&arg1, Arg2 &&arg2) {
   return arg1 + arg2;
}

Но вот беда, если пытаюсь соединить таким образом n кортежей, то gcc скомпилирует это все нормально, а clang на меня ругается

constexpr decltype(auto) multiple_concat() {
  return ::std::make_tuple();
}

template <class... Args>
constexpr decltype(auto) multiple_concat(Args &&... args) {
   return (args + ...);
}

И вот я думаю, толь clang мой не едет, толь я - тупой

Выхлоп clang'а:

error: call to function 'operator+' that is neither visible in the template definition nor found by argument-dependent lookup return (args + ...);

note: in instantiation of function template specialization 'multiple_concat<std::__1::tuple<int, int> &, std::__1::tuple<int, char> &>' requested here multiple_concat(tup1, tup2);

note: 'operator+' should be declared prior to the call site constexpr decltype(auto) operator+(const ::std::tuple<Args1...> &tup1,

1 error generated.

Пример на Wanbox'е

P.S: Не работает ни с 4.0.1, ни с 5.0 (branches/release_50 309888), ни с 6.0 (trunk 310399) версией

 

maxis11
()

Первый альфа релиз ideal-couscous

Первый альфа релиз ideal-couscous - библиотека(header only) для с++17 реализует статичную рефлексию (с ограничениями). Изменения после последней публикации:

  • Разбил хедеры и упорядочил их по категориям (метапрограммирование(metautils), информация о классах(info), функции рефлексии(utils)).
  • Переработал процесс сбора информации о рефлексии. Если раньше для каждого типа (объектные методы, статичные методы, переменные, и.т.д.) был свой кортеж информации и имен, и были свои функции работы с ними, то теперь это все унифицировано в два кортежа. Добавлены генераторы индексов, которые теперь отдают индекса элементов(например: индексы всех переменных), что позволило реализовать систему независимых плагинов, где теперь можно писать свою логику обработки информации тех или иных данных.
  • Добавлена doxygen документация (пока что просто пояснения по каждой функции или структуре/объекта)
  • Так как любая ошибка в вызове функций рефлексии, практически всегда генерировала адовую простыню ошибок (бывало по 200 строк(шаблоны, они такие) ), то во всех функций в пространстве utils теперь проводится статичные проверки на правильность входных данных (класс зарефлексирован, проверки выхода за границу, и.т.д.) и возвращается boost::hana::optional с данными или без (в будущем я, наверно, добавлю возможность отключения большинства проверок)
  • Добавлена возможность вынесения метаинформации за предел класса (OUT_METAINFO)
  • Добавлены туториалы где показываются как работает библиотека (расположена в examples/tutorial)
  • Изменил лицензию с GPLv3 на Apache 2.0

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

ссылка на проект

 , ,

maxis11
()

Compile-time рефлексия на c++1z

Я тут с начала октября пишу свою реализацию с Compile-time рефлексии, и у меня в итоге появились первые результаты работы. Что в ней есть:

  • Счетчики методов/переменных
  • Получение/присвоение переменных через индекс
  • Поиск переменных по имени
  • Получение типа переменной
  • статичные переменные
  • Получение имени класса
  • запуск методов через индекс
  • получение типа возвращаемого значения метода, получение типов входных аргументов
  • константный методы
  • статичные методы
  • Поиск методов по имени
  • попытка запустить кучу методов (там кортеж из индексов на вход идёт) с данными аргументами, неудача не ведет к ошибки компиляции(sfinae)
  • Получение имени переменной/метода

Я пока не делал документацию, и оформление кода хромает. Но это все уже активно пилится. Зависимости: boost.hana, boost.type_index (только в первом примере используется). Из С++1z: Поддержка if constexpr (), std::conjunction.

Подробности:

Ссылка на проект

Первый пример

Второй пример

Скриншот выхлопа первого примера

Скриншот выхлопа второго примера

P.S: Да макросы и не красиво, но с таким функционал без них никак не обойтись.

P.S.S: В файле utils можно убрать namespace std {...} если у Вас std::is_*_v уже в стандартной библиотеке определены.

P.S.S.S: лицензия GPLv3.

 , ,

maxis11
()

RSS подписка на новые темы