
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.11] |
![]() |
|
Страницы: (16) « Первая ... 9 10 [11] 12 13 ... 15 16 все ( Перейти к последнему сообщению ) |
Сообщ.
#151
,
|
|
|
Я заметил. Это просто отвлечённый пример-иллюстрация к тому, как можно "эффективно" принимать решения, не выяснив - что именно не так с системой. Добавлено Можно. И сам объект, к которому он применяется - можно. Более того, ты именно так и делаешь в своём примере с первой страницы. |
Сообщ.
#152
,
|
|
|
Цитата Flex Ferrum @ Ну, не знаю. Когда при мне занимались оптимизацией (и когда я сам в ней участвовал) задача была вписаться в те или иные требования по производительности и потребляемым при этом ресурсам. И ставилась она не в формулировках "давайте заоптимизируем вот этот кусок кода", а "видишь график распределения времени по функциям? Я не спорю, иногда это нужно. Но, думаю, в большинстве случаев следует начинать с анализа кода, тогда и задачи такой не возникнет. |
Сообщ.
#153
,
|
|
|
Цитата Олег М @ Но, думаю, в большинстве случаев следует начинать с анализа кода, тогда и задачи такой не возникнет. Во всех случаях надо начинать с анализа статистики работы программы. Если она удовлетворяет требованиям - то и дёргаться смысла нет. А вот если не удовлетворяет - то нужно "брать анализы", везти на рентген-МРТ и прочие инструментальные средства диагностики. И только после этого лечить. |
Сообщ.
#154
,
|
|
|
Цитата Flex Ferrum @ Можно. И сам объект, к которому он применяется - можно. Более того, ты именно так и делаешь в своём примере с первой страницы. Нет, я так не делаю. Ни в коем случае. Этот метод можно вызывать только для копии shared_ptr. |
Сообщ.
#155
,
|
|
|
Цитата Олег М @ Нет, я так не делаю. Ни в коем случае. Этот метод можно вызывать только для копии shared_ptr. Посмотри внимательно. Ещё раз. У тебя в глобальном скоупе weak_ptr и shared_ptr. Ты передаёшь их (по ссылке) в рабочие потоки. Потом каждый из этих потоков начинает активно работать с этими самыми глобальными shared_ptr/weak_ptr. Не с собственными копиями, а с глобальными. То есть у тебя основной поток и два рабочих шарят между собой один shared_ptr и один weak_ptr. ![]() |
Сообщ.
#156
,
|
|
|
Цитата Flex Ferrum @ Посмотри внимательно. Ещё раз. У тебя в глобальном скоупе weak_ptr и shared_ptr. Ты передаёшь их (по ссылке) в рабочие потоки. Потом каждый из этих потоков начинает активно работать с этими самыми глобальными shared_ptr/weak_ptr. Не с собственными копиями, а с глобальными. То есть у тебя основной поток и два рабочих шарят между собой один shared_ptr и один weak_ptr. Ну, так у тебя написано. Ты посмотри внимательно: во втором потоке я я вызываю weak_ptr::lock, т.е. создаю новый shared_ptr. И потом работаю только с ним. Это и требуется. ![]() ![]() auto sp = sp2.lock(); if (sp) std::cout << (++i) << ", " << *sp << std::endl; Добавлено В первом потоке я не обращаюсь к содержимому указателей |
Сообщ.
#157
,
|
|
|
Цитата Олег М @ Ну, ты мне так и не ответил, какие именно методы должны быть потокобезопасными. Рассмотрим сценарий, когда один поток вызывает конструктор копирования, а другой ShPtrIntLockedTh<T>::DisConnect: 1-й: вызывает DisConnect(), потом DisConnectSlave(), который возвращает true 2-й: вызывает ShPtrIntLockedTh(const ShPtrIntLockedTh& p), проверяет p.StatPtr, который != null, делает StatPtr = p.StatPtr; 1-й: делает delete StatPtr 2-й: вызывает StatPtr->IncCount(); Т.е. пытается изменить удалённый объект Нет, я полагаю, что ты ошибаешься. Дело в том, что когда Цитата "DisConnectSlave(), который возвращает true" автоматически означает - это был последний SP в группе. И никакого другого SP хоть в потоке, хоть где-нибудь уже нет. А значит ситуации, описанной тобой, быть не может. --- Вероятно, твои рассуждения происходят от непонимания самого назначения и использования SP. SP - это как заявка из различных точек твоего приложения на какой-то ресурс. Попытка использования одного и того-же экземпляра SP из разных архитектурных точек приложения (например из разных потоков) совершенно не верна. Такую архитектуру надо менять, а не специальный SP придумывать. |
Сообщ.
#158
,
|
|
|
Цитата ЫукпШ @ Нет, я полагаю, что ты ошибаешься. Дело в том, что когда Когда между вызовами ShPtrIntLockedTh(const ShPtrIntLockedTh& p) и StatPtr->IncCount() вызовется DisConnect(), для p. Программа у тебя не падает, потому что такие вызовы либо очень редкие, либо не выполняются одновременно, тогда это уже не многопоточность. Я однажды тоже с таким столкнулся - неожиданно выяснил, что запросы, которые должны по задумки отрабатывать параллельно, выполняются последовательно. Цитата ЫукпШ @ Попытка использования одного и того-же экземпляра SP из разных архитектурных точек приложения (например из разных потоков) совершенно не верна. Не использования, а копирования. Которое и должно быть безопасным. И именно из потоков. |
Сообщ.
#159
,
|
|
|
Цитата Олег М @ Программа у тебя не падает, потому что такие вызовы либо очень редкие, Не поэтому. Не падает потому, что я "такого" не делаю, поскольку полагаю, что это не правильно. Создал объект, затем группу - раздал кому требуется, а дальше - владейте. Можете ещё подсоединяться к группе/отсоединяться от неё. --- Если ты хочешь обеспечить потоко-безопасность создания/уничтожения группы, то это уже другая проблема. Очевидно, такой синхронизатор не может принадлежать самой группе - тут и спорить не о чем. Но это означает, что придётся сделать общий синхронизатор для всех объектов SP, в том числе - разных групп и разных типов. Да, это можно, но недостаток такого объекта очевиден - все группы связаны друг с другом. Такое я тоже делал, но мне это не очень интересно. Вот что получилось: Прикреплённый файл ![]() --- Впрочем, можно предложить совсем уже экзотический вариант. Можно прекратить процесс автоматического создания/уничтожения группы. Создавать группы как отдельные объекты (где-то в приложении, массивом например), а SP передавать адреса на них. Тогда синхронизатор может быть внутри группы. Получится из этой идеи что-нибудь удобное или нет - не знаю. Такого я не делал. |
Сообщ.
#160
,
|
|
|
Цитата ЫукпШ @ Не поэтому. Не падает потому, что я "такого" не делаю, поскольку полагаю, что это не правильно. Я правильно тебя понял, что те классы которые ты присылал не работают в потоках. Т.е. никакие методы у них не вызываются одновременно? Добавлено Цитата ЫукпШ @ Такое я тоже делал, но мне это не очень интересно. Вот что получилось: Я правильно понимаю, что csShell cssh(&csp); - это блокировка критической секции? Которая объявлена как static MCS csp;? В каждом методе? |
Сообщ.
#161
,
|
|
|
Цитата Олег М @ В первом потоке я не обращаюсь к содержимому указателей Ну, давай смотреть. Первый поток: ![]() ![]() sp.reset(new std::string("!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111111111111111111111111111111")); sp2 = sp; Ты модифицируешь глобальный shared_ptr (sp) и перезаписываешь глобальный же weak_ptr (sp2). Второй поток: ![]() ![]() auto sp = sp2.lock(); ты пытаешься лочить значение глобального weak_ptr (sp2). Фактически, получаешь data race на доступе к этому самому weak_ptr. И это логично. Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны. Поэтому я и говорю: Цитата Flex Ferrum @ Тебе нужен что-то в стиле RemoteObjectHolder. Это не столько указатель, сколько сервисный класс, контролирующий доступ к объекту из разных потоков, его операбельность и прочие подобные фишки. Ну, насколько я понял твою задачу. |
Сообщ.
#162
,
|
|
|
Цитата Flex Ferrum @ Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны. Да, именно это я и хочу сделать. Собственно, и сделал. Мои классы здесь работают. Насчёт RemoteObjectHolder - т.е. ты предлагаешь, чтобы создание/удаление объекта занимало время, зависящее от количества объектов? В то время, как shared_ptr/weak_ptr вполне справляются с этим за константное время? Это как минимум. А вообще, думаю там придется писать довольно много кода, вместо простого reset(). |
Сообщ.
#163
,
|
|
|
Цитата Олег М @ Цитата Flex Ferrum @ Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны. Да, именно это я и хочу сделать. Собственно, и сделал. Мои классы здесь работают. Насчёт RemoteObjectHolder - т.е. ты предлагаешь, чтобы создание/удаление объекта занимало время, зависящее от количества объектов? В то время, как shared_ptr/weak_ptr вполне справляются с этим за константное время? Это как минимум. А вообще, думаю там придется писать довольно много кода, вместо простого reset(). Я не совсем понял, что ты имеешь в виду. Смарт-указатели не создают объекты, они контролируют их время жизни. А тебе (плюс к этому) надо контролировать ещё и доступ. А вот время жизни, к слову, не надо. Семантика обычного shared_ptr тут не подойдёт - копии shared_ptr'a, даже изначально указывающие на один объект, независимы (именно поэтому тебе требуется обновлять weak_ptr после reset). Таким образом выходит, что тебе нужна сущность, которая иниициализируется/обновляется в одном месте (строго в одном), используется строго в другом. Ссылки использования тебе при этом считать не то, чтобы требуется - ты их и так знаешь. Можно, конечно, продолжить извращаться с shared_ptr'ами и их аналогами (потокобезопасными), но это как сову на глобус натягивать. |
Сообщ.
#164
,
|
|
|
Цитата Flex Ferrum @ Смарт-указатели не создают объекты, они контролируют их время жизни. А тебе (плюс к этому) надо контролировать ещё и доступ. А вот время жизни, к слову, не надо. Семантика обычного shared_ptr тут не подойдёт - копии shared_ptr'a, даже изначально указывающие на один объект, независимы (именно поэтому тебе требуется обновлять weak_ptr после reset). Недостаточно просто создать объект, его ещё нужно потом и удалить. Т.е. создание объекта и контроль за временем его жизни две неразрывно связанные задачи. И если, после создания объекта мне будет необходимо впихивать его в какие-то контейнеры, а перед удалением оттуда его вытаскивать, вместо того, чтобы просто создать или присвоить переменную, то это как-то накладно получиться. Замучишься потом профилировать, где у тебя тормозит. SharedPtr не доступ контролирует, а именно время жизни. Собственно, он принимает решение, когда объект нужно удалить. Использование - это вызов оператора ->. Добавлено Цитата Олег М @ . Можно, конечно, продолжить извращаться с shared_ptr'ами и их аналогами (потокобезопасными), но это как сову на глобус натягивать. Т.е. ты не смог написать такой класс? |
Сообщ.
#165
,
|
|
|
Кстати у майкрософта, в msdn, по поводу shared_ptr написано следующее
Цитата Thread Safety Multiple threads can read and write different shared_ptr objects at the same time, even when the objects are copies that share ownership. Ну, тут они несколько привирают. Потому что тоже не работает, во всяком случае в 2010 студии. |