На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (16) « Первая ... 9 10 [11] 12 13 ...  15 16 все  ( Перейти к последнему сообщению )  
> Thread-safe shared_ptr , Реализация потоко-безопасного SharedPtr
    Цитата Олег М @
    Вообще, если ты не заметил, то я пришёл сюда не жаловаться на что либо.

    Я заметил. Это просто отвлечённый пример-иллюстрация к тому, как можно "эффективно" принимать решения, не выяснив - что именно не так с системой.

    Добавлено
    Цитата Олег М @
    Я слабо представляю, как operator-> можно использовать в разных потоках

    Можно. И сам объект, к которому он применяется - можно. Более того, ты именно так и делаешь в своём примере с первой страницы.
      Цитата Flex Ferrum @
      Ну, не знаю. Когда при мне занимались оптимизацией (и когда я сам в ней участвовал) задача была вписаться в те или иные требования по производительности и потребляемым при этом ресурсам. И ставилась она не в формулировках "давайте заоптимизируем вот этот кусок кода", а "видишь график распределения времени по функциям?


      Я не спорю, иногда это нужно.
      Но, думаю, в большинстве случаев следует начинать с анализа кода, тогда и задачи такой не возникнет.
        Цитата Олег М @
        Но, думаю, в большинстве случаев следует начинать с анализа кода, тогда и задачи такой не возникнет.

        Во всех случаях надо начинать с анализа статистики работы программы. Если она удовлетворяет требованиям - то и дёргаться смысла нет. А вот если не удовлетворяет - то нужно "брать анализы", везти на рентген-МРТ и прочие инструментальные средства диагностики. И только после этого лечить.
          Цитата Flex Ferrum @
          Можно. И сам объект, к которому он применяется - можно. Более того, ты именно так и делаешь в своём примере с первой страницы.


          Нет, я так не делаю. Ни в коем случае. Этот метод можно вызывать только для копии shared_ptr.
            Цитата Олег М @
            Нет, я так не делаю. Ни в коем случае. Этот метод можно вызывать только для копии shared_ptr.

            Посмотри внимательно. Ещё раз. У тебя в глобальном скоупе weak_ptr и shared_ptr. Ты передаёшь их (по ссылке) в рабочие потоки. Потом каждый из этих потоков начинает активно работать с этими самыми глобальными shared_ptr/weak_ptr. Не с собственными копиями, а с глобальными. То есть у тебя основной поток и два рабочих шарят между собой один shared_ptr и один weak_ptr. :-? Ну, так у тебя написано.
              Цитата Flex Ferrum @
              Посмотри внимательно. Ещё раз. У тебя в глобальном скоупе weak_ptr и shared_ptr. Ты передаёшь их (по ссылке) в рабочие потоки. Потом каждый из этих потоков начинает активно работать с этими самыми глобальными shared_ptr/weak_ptr. Не с собственными копиями, а с глобальными. То есть у тебя основной поток и два рабочих шарят между собой один shared_ptr и один weak_ptr. Ну, так у тебя написано.


              Ты посмотри внимательно: во втором потоке я я вызываю weak_ptr::lock, т.е. создаю новый shared_ptr. И потом работаю только с ним. Это и требуется.

              ExpandedWrap disabled
                        auto sp = sp2.lock();
                        if (sp)
                            std::cout << (++i) << ", " << *sp << std::endl;


              Добавлено
              В первом потоке я не обращаюсь к содержимому указателей
                Цитата Олег М @
                Ну, ты мне так и не ответил, какие именно методы должны быть потокобезопасными.

                Рассмотрим сценарий, когда один поток вызывает конструктор копирования, а другой 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 придумывать.
                Сообщение отредактировано: ЫукпШ -
                  Цитата ЫукпШ @
                  Нет, я полагаю, что ты ошибаешься.
                  Дело в том, что когда


                  Когда между вызовами ShPtrIntLockedTh(const ShPtrIntLockedTh& p) и StatPtr->IncCount() вызовется DisConnect(), для p.

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

                  Цитата ЫукпШ @
                  Попытка использования одного и того-же экземпляра SP из разных архитектурных точек приложения
                  (например из разных потоков) совершенно не верна.


                  Не использования, а копирования. Которое и должно быть безопасным. И именно из потоков.
                    Цитата Олег М @
                    Программа у тебя не падает, потому что такие вызовы либо очень редкие,

                    Не поэтому.
                    Не падает потому, что я "такого" не делаю, поскольку полагаю, что это не правильно.
                    Создал объект, затем группу - раздал кому требуется, а дальше - владейте.
                    Можете ещё подсоединяться к группе/отсоединяться от неё.
                    ---
                    Если ты хочешь обеспечить потоко-безопасность создания/уничтожения группы,
                    то это уже другая проблема.
                    Очевидно, такой синхронизатор не может принадлежать самой группе - тут и спорить не о чем.
                    Но это означает, что придётся сделать общий синхронизатор для всех объектов SP,
                    в том числе - разных групп и разных типов. Да, это можно, но недостаток такого
                    объекта очевиден - все группы связаны друг с другом.
                    Такое я тоже делал, но мне это не очень интересно.
                    Вот что получилось:

                    Прикреплённый файлПрикреплённый файлshared_ptr_Th.zip (2,08 Кбайт, скачиваний: 104)
                    ---
                    Впрочем, можно предложить совсем уже экзотический вариант.
                    Можно прекратить процесс автоматического создания/уничтожения группы.
                    Создавать группы как отдельные объекты (где-то в приложении, массивом например), а SP передавать адреса на них.
                    Тогда синхронизатор может быть внутри группы.
                    Получится из этой идеи что-нибудь удобное или нет - не знаю.
                    Такого я не делал.
                    Сообщение отредактировано: ЫукпШ -
                      Цитата ЫукпШ @
                      Не поэтому.
                      Не падает потому, что я "такого" не делаю, поскольку полагаю, что это не правильно.


                      Я правильно тебя понял, что те классы которые ты присылал не работают в потоках. Т.е. никакие методы у них не вызываются одновременно?

                      Добавлено
                      Цитата ЫукпШ @
                      Такое я тоже делал, но мне это не очень интересно.
                      Вот что получилось:


                      Я правильно понимаю, что csShell cssh(&csp); - это блокировка критической секции? Которая объявлена как static MCS csp;?
                      В каждом методе?
                        Цитата Олег М @
                        В первом потоке я не обращаюсь к содержимому указателей

                        Ну, давай смотреть.
                        Первый поток:
                        ExpandedWrap disabled
                          sp.reset(new std::string("!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111111111111111111111111111111"));
                          sp2 = sp;

                        Ты модифицируешь глобальный shared_ptr (sp) и перезаписываешь глобальный же weak_ptr (sp2). Второй поток:
                        ExpandedWrap disabled
                          auto sp = sp2.lock();

                        ты пытаешься лочить значение глобального weak_ptr (sp2). Фактически, получаешь data race на доступе к этому самому weak_ptr. И это логично. Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны. Поэтому я и говорю:
                        Цитата Flex Ferrum @
                        Тебе нужен что-то в стиле RemoteObjectHolder. Это не столько указатель, сколько сервисный класс, контролирующий доступ к объекту из разных потоков, его операбельность и прочие подобные фишки. Ну, насколько я понял твою задачу.
                          Цитата Flex Ferrum @
                          Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны.


                          Да, именно это я и хочу сделать. Собственно, и сделал. Мои классы здесь работают.

                          Насчёт RemoteObjectHolder - т.е. ты предлагаешь, чтобы создание/удаление объекта занимало время, зависящее от количества объектов? В то время, как shared_ptr/weak_ptr вполне справляются с этим за константное время?
                          Это как минимум. А вообще, думаю там придется писать довольно много кода, вместо простого reset().
                            Цитата Олег М @
                            Цитата Flex Ferrum @
                            Ты хочешь сделать то, что хочешь, но стандартные указатели на это не рассчитаны.


                            Да, именно это я и хочу сделать. Собственно, и сделал. Мои классы здесь работают.

                            Насчёт RemoteObjectHolder - т.е. ты предлагаешь, чтобы создание/удаление объекта занимало время, зависящее от количества объектов? В то время, как shared_ptr/weak_ptr вполне справляются с этим за константное время?
                            Это как минимум. А вообще, думаю там придется писать довольно много кода, вместо простого reset().

                            Я не совсем понял, что ты имеешь в виду. Смарт-указатели не создают объекты, они контролируют их время жизни. А тебе (плюс к этому) надо контролировать ещё и доступ. А вот время жизни, к слову, не надо. Семантика обычного shared_ptr тут не подойдёт - копии shared_ptr'a, даже изначально указывающие на один объект, независимы (именно поэтому тебе требуется обновлять weak_ptr после reset). Таким образом выходит, что тебе нужна сущность, которая иниициализируется/обновляется в одном месте (строго в одном), используется строго в другом. Ссылки использования тебе при этом считать не то, чтобы требуется - ты их и так знаешь. Можно, конечно, продолжить извращаться с shared_ptr'ами и их аналогами (потокобезопасными), но это как сову на глобус натягивать.
                            Сообщение отредактировано: Flex Ferrum -
                              Цитата Flex Ferrum @
                              Смарт-указатели не создают объекты, они контролируют их время жизни. А тебе (плюс к этому) надо контролировать ещё и доступ. А вот время жизни, к слову, не надо. Семантика обычного shared_ptr тут не подойдёт - копии shared_ptr'a, даже изначально указывающие на один объект, независимы (именно поэтому тебе требуется обновлять weak_ptr после reset).


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


                              SharedPtr не доступ контролирует, а именно время жизни. Собственно, он принимает решение, когда объект нужно удалить.
                              Использование - это вызов оператора ->.

                              Добавлено
                              Цитата Олег М @
                              . Можно, конечно, продолжить извращаться с shared_ptr'ами и их аналогами (потокобезопасными), но это как сову на глобус натягивать.

                              Т.е. ты не смог написать такой класс?
                                Кстати у майкрософта, в 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 студии.
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (16) « Первая ... 9 10 [11] 12 13 ...  15 16 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0603 ]   [ 17 queries used ]   [ Generated: 18.07.25, 18:49 GMT ]