|
0 / 0 / 0
Регистрация: 13.09.2018
Сообщений: 25
|
||||||
Динамический vector<shared_ptr<T>> и многопоточность12.02.2020, 00:14. Показов 1926. Ответов 13
Метки нет (Все метки)
Как защитить вызов удалённого из памяти объекта в другом потоке?
0
|
||||||
| 12.02.2020, 00:14 | |
|
Ответы с готовыми решениями:
13
shared_ptr и vector Динамический массив на shared_ptr Собственный динамический массив (аналог std::vector) |
|
1741 / 913 / 480
Регистрация: 05.12.2013
Сообщений: 3,074
|
||
| 12.02.2020, 00:20 | ||
|
1
|
||
|
0 / 0 / 0
Регистрация: 13.09.2018
Сообщений: 25
|
|
| 12.02.2020, 00:23 [ТС] | |
|
Ну тогда контейнер будет раздуваться с каждым выстрелом.
Всё же должен быть способ как отследить удалён ли объект, и если удалён то игнорировать его полностью.
0
|
|
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|||||||
| 12.02.2020, 10:00 | |||||||
0
|
|||||||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||
| 12.02.2020, 12:33 | |||||||
|
A553M613R, буквально на днях решал подобную задачу. на самом деле у тебя есть ровно 3 пути решения: 1. лочить весь контейнер (это тупо, не эффективно и медленно) с таким подходом можно вообще не использовать многопоточность. 2. использовать lock-free (это предмет особой олимпиады) увлекательный мир сложно-замороченных вещей. 3. lock-free для гуманитариев))) если ты не хочешь погрязнуть надолго в деталях lock-free, и тебе просто нужно по быстрому порешать задачу, то этот способ для тебя. идея очень простая: - захват свободного мутекса почти бесплатен. - ожидание занятого мутекса - дорого. ситуация, когда один тред вынужден ждать освобождения мутекса назовем коллизией. коллизии - нежелательны. они снижают эффективность работы. соответственно, всё что нужно, что бы получить эффективный алгоритм, это таким образом организовать структуру данных, что бы минимизировать вероятность возникновения коллизий. если сама по себе вероятность возникновения коллизий незначительная, тогда можно считать, что алгоритм вполне себе эффективен и без всех этих вундер-вафель в моём случае у меня был банк данных: map<login, activities>когда юзер совершал какое то действие, то из некоторого (заранее неизвестного) треда осуществлялся доступ к активностям по логину. наиболее старые (неактуальные) активности удалялись, новая дозаписывалась. ключи никогда не удалялись. если же юзер переставал совершать действия (ушел в офф-лайн), тогда его старые активности так и висели в памяти до бесконечности. через какое то время оказывалось, что в памяти хранится колоссальное количество бесполезных, никому не нужных данных, об активностях пользователей, которые как прошлогодний снег: недельной давности. что сделал я: разбил общий банк памяти на 100 частей в виде двух-мерного массива: data[10][10]где data - это map<login_id, activities>логин юзера представляет собой обычное число. например: 424968, 520082, 535877 две последние цифры в числе логина - это координаты ячейки в двухмерном массиве, где хранится ключ данного логина. например, логин 424968:
хотя достигается она очень простым способом. далее я просто создал отдельный поток, который неспеша, медленно, не более чем по 25 штук логинов за раз (много и не нужно), с 5 секундными интервалами времени пробегается по всем ячейками массива, и проверяет: если активность слишком старая, тогда удаляет запись. важный момент: мусоросборщик не должен мешать работе других тредов. нужно так подобрать для него параметры, что бы он относительно редко активничал, но в тоже время за определенное время (например, за сутки), успевал обработать минимально необходимый объём. конечно, что бы удалить запись из контейнера, его необходимо лочить. однако, одно дело лочить сразу всё, и совсем другое - только 1/100 часть данных. логины из других ячеек могут обрабатываться параллельно без задержек. а удаление данных из маленького блока относительно быстро. можно спинлоком лочить, а не мутексом. итого: - разбивай большой банк данных на множество более маленьких блоков. - активно пишушие треды не должны удалять ключи, а только помечать их как неактуальные - непосредственным удалением ключей занимается отдельный фоновый поток "мусоровозка" (привет, garbage collector!) - PROFIT ???
3
|
|||||||
|
Just Do It!
|
|||||||
| 12.02.2020, 14:37 | |||||||
|
без заумностей, простейшая синхронизация:
это первая итерация. если будет работать, (как критично на недорисовку), то можно слегка усовершенствовать.
0
|
|||||||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
||
| 12.02.2020, 15:20 | ||
|
Второе - если во время вызова bullet->Draw(); этот элемент будет удалён в UpdateThread, то всё тоже будет плохо
1
|
||
|
0 / 0 / 0
Регистрация: 13.09.2018
Сообщений: 25
|
|
| 12.02.2020, 22:47 [ТС] | |
|
hoggy, очень познавательный ответ.
Какой из предложенных вариантов посоветуешь использовать для многопользовательской real-time PvP игры?
0
|
|
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
||
| 12.02.2020, 23:05 | ||
|
1) Draw - константный метод. 2) Основные расходы времени идут не на чтение tank, а на отрисовку. Таким образом, просто создайте локальную копию vec_tank, в которой будут локальные копии танчиков. В этом случае вам придется лочить доступ только на время создания локальной копии. А на время отрисовки можно неспеша читать локальную копию, не беспокоясь о синхронизациях.
0
|
||
|
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
|
|
| 12.02.2020, 23:22 | |
|
Можно так:
Пока рисуются танки, обсчитывать пули. Пока рисуются пули, обсчитывать танки. Использовать вектор shared_ptr для короткоживущих объектов, да еще и использовать erase - то еще извращение. Используй пулы. Раздели ресурсы, которые используются в совместных расчетах, но не нужны при отрисовке (boundin_box танков, для расчета попадания пуль, например), в отдельном пуле.
0
|
|
|
Неэпический
|
||||||
| 13.02.2020, 00:14 | ||||||
|
A553M613R, вы пытаетесь распараллелить заведомо последовательные операции. Зачем? Ничего кроме проблем и худшей работоспособности вы не получите. Если уж так хотите отрисовку кадра в другом потоке, то, если новый кадр еще не готов, рисуйте старый:
То есть распараллеливать задачи нужно так, чтобы они не требовали синхронизации, либо чтобы имели минимальные точки соприкосновения. В ином случае вы получите мало крупногранулярных блокировок и потоки будут ждать друг-друга постоянно, либо получите дохреналиард мелкогранулярных блокировок, что тоже ни к чему хорошему не приведет, начиная с снижения производительности и заканчивая неуловимыми багами.
3
|
||||||
|
0 / 0 / 0
Регистрация: 13.09.2018
Сообщений: 25
|
|
| 16.02.2020, 02:32 [ТС] | |
|
Подумал я несколько дней и решил реализовать это таким образом:
Создать интерфейсы с максимально возможным наименьшим объёмом данных у динамических объектов. При окончании жизни объекта превращать его в абстрактный класс и удалять их в специально отведённое для этого время. Например если все элементы равны элементам абстрактного класса. Таким образом размер динамического контейнера во время обработки останется прежним, это поможет избежать неявное обращение к удалённому из памяти объекта. Всем спасибо!
0
|
|
|
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
|
|
| 16.02.2020, 06:03 | |
|
Как-то у вас всё в кучу получилось.
Croessmah правильно сказал. Рендер должен произойти строго после апдейта. Во время рендера стейты объектов меняться не должны. Попробуйте Data-Oriented Design. Он существенно упростит код и уменьшит количество выстрелов в ногу. Так же рекомендую посмотреть паттерн Entity-Component-System и любые его вариации. Ну и конечно же книга Game Programming Patterns. Доступная в сети.
2
|
|
| 16.02.2020, 06:03 | |
|
Помогаю со студенческими работами здесь
14
На основе контейнера vector построить двумерный динамический массив Реализовать шаблон класса vector, реализующий динамический массив Что лучше использовать библиотеку <vector> или динамический массив
Многопоточность - как создать динамический массив потоков Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
|
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
|
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
|
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования.
Часть библиотеки BedvitCOM
Использованы. . .
|
|
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога
SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
|
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога
SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
|
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
|
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога
SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
|