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


    Интернет-брокер

    Добавлено
    Цитата ЫукпШ @
    Попробуем сначала.
    1. Будем писать шаблонный класс SP - группа объектов указывает на какой-то объект в памяти.
    SP должен уметь создать группу, уничтожить группу и объект, присоединиться к группе, отсоединиться
    от группы. Обеспечить доступ к объекту. Желательно возможность модификации объекта как-нибудь по-проще.


    Что-то никак могу взять в толк, что именно требуется. Не доходит.
    А можешь как-то грубо накидать в виде классов, без потоков, чисто символически. Мне так проще понять будет.
      Цитата Олег М @
      А можешь как-то грубо накидать в виде классов,

      Вот, сделал оба варианта.
      В многопоточном приложении проверил оба, но не запредельно подробно.
      Прикреплённый файлПрикреплённый файлShPtrs.zip (4,29 Кбайт, скачиваний: 98)
      Сообщение отредактировано: ЫукпШ -
        Цитата ЫукпШ @
        Вот, сделал оба варианта.
        В многопоточном приложении проверил оба, но не запредельно подробно.


        Т.е. насколько я понял:
        - У тебя есть указатель и счётчик ссылок, class Status, который при обнулении которого этот указатель кто-то должен будет удалить, в частности ShPtrIntLockedTh.
        - ShPtrIntLockedTh хранит у себя указатель на этот class Status и флажок memArray, который определяет, на что указывает Status, но кроме вызова delete нигде больше не используется.
        - Безопасно тебе нужно только удалять содержимое Status.

        Правильно?

        Если да, то с ходу можно сказать, что class Status у тебя ни разу не потокобезопасный и ничего толком не защищает. Большие сомнения, что код вообще работает.

        Добавлено
        Вообще, это поведение очень сильно напоминает поведение shared_ptr, и я бы им и воспользовался.

        А так все средства и методы, необходимые для решения этой задачи у меня вроде показаны
        - class Status {CRefCounter Count; UT *RealPtr;}
        - ShPtrIntLockedTh<T>::DisConnectSlave - деструктор CSharedPtr, вернее строчка if (ref.m_p && ref.m_cnt->m_refs.Release()) delete ref.m_p;
        И дальше, по аналогии
          По поводу memArray - диковатая довольно штука, особенно с учётом того, что этот флажок можно устанавливать независимо от указателя.

          Я бы тут сделал примерно так
          ExpandedWrap disabled
            template <class T>
            class ShPtrIntLockedTh
            {
            public:
                template <typename T2>
                ShPtrIntLockedTh(std::unique_ptr<T2> sp)
                : m_p(sp.get())
                , m_deleter(sp.get_deleter())
                {
                    //Status = new Status() !!!Здесь может возникнуть исключение
             
                    sp.release();
                }
             
                ~ShPtrIntLockedTh()
                {
                    /////if (....)
                        m_deleter(m_p);
                }
            protected:
                T *m_p;
                std::function<void(T *)> m_deleter;
            };
          Сообщение отредактировано: Олег М -
            Цитата Олег М @
            Попробуем сначала.
            1. Будем писать шаблонный класс SP - группа объектов указывает на какой-то объект в памяти.
            SP должен уметь создать группу, уничтожить группу и объект, присоединиться к группе, отсоединиться
            от группы. Обеспечить доступ к объекту. Желательно возможность модификации объекта как-нибудь по-проще.
            2. Имеется счётчик ссылок.
            3. Предполагаем волюнтаристским способом, что создание или уничтожение группы - потокобезопасно (ПБ).
            Поскольку оба действия предполагают наличие только одного объекта SP.


            Судя по коду, тебе наверное нужно что-то наподобие вот этого
            ExpandedWrap disabled
              template <typename T>
              class CCountedPtr
              {
              public:
                  template <typename T_>
                  static std::unique_ptr<CCountedPtr> Create(std::unique_ptr<T_> sp)
                  {
                      return sp? std::make_unique<CCountedPtr>(sp): nullptr;
                  }
               
                  static CCountedPtr *Copy(const CCountedPtr *p) noexcept
                  {
                      TS_LOCK(GetSharedPtrLock());
                      return p && p->m_refs.AddRef()? p: nullptr;
                  }
               
                  void Release() noexcept
                  {
                      if (m_refs.Release())
                      {
                          m_deleter(m_p);
                          GetSharedPtrLock().Wait();
                          delete this;
                      }
                  }
               
                  T *get() const noexcept
                  {
                      return m_p;
                  }
               
              protected:
                  template <typename T_>
                  CCountedPtr(std::unique_ptr<T_> sp)
                  : m_p(sp.get())
                  , m_deleter(sp.get_deleter())
                  {
                      sp.release();
                  }
               
                  ~CCountedPtr()
                  {
                      if (m_p)
                          m_deleter(m_p);
                  }
               
                  static CSharedPtrLock &GetSharedPtrLock() noexcept
                  {
                      static CSharedPtrLock _lock;
                      return _lock;
                  }
               
                  T *m_p = nullptr;
                  std::function<void(T *)> m_deleter;
                  mutable CRefCounter m_refs;
              };
               
              template <typename T>
              class CSinglePtr
              {
              public:
                  template <typename T_>
                  CSinglePtr(std::unique_ptr<T_> sp)
                  : m_p(CCountedPtr<T>::Create(std::move(sp)).release())
                  {
                  }
               
                  CSinglePtr(const CSinglePtr &src)
                  : m_p(CCountedPtr<T>::Copy(src.m_p))
                  {
                  }
               
                  ~CSinglePtr()
                  {
                      if (m_p)
                          m_p->Release();
                  }
               
                  void reset()
                  {
                      if (m_p)
                      {
                          m_p->Release();
                          m_p = nullptr;
                      }
                  }
               
                  T *get() const
                  {
                      return m_p? m_p->get(): nullptr;
                  }
              protected:
                  CCountedPtr<T> *m_p;
              };


            На intrlocked-функции заменяется достаточно легко - убираешь атомик и подставляешь вместо его методов и операторов соответствующие функции
            Сообщение отредактировано: Олег М -
              Цитата Олег М @
              - Безопасно тебе нужно только удалять содержимое Status.

              Правильно?

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


                Это и имелось ввиду - безопасно определить, что ссылок больше нет и удалить объект, ShPtrIntLockedTh<T>::DisConnectSlave. Так?
                  Цитата Олег М @
                  Это и имелось ввиду - безопасно определить, что ссылок больше нет и удалить объект, ShPtrIntLockedTh<T>::DisConnectSlave. Так?

                  Да. Если декремент сделан потоко-безопасно и в результате 0,
                  значит работаем с последним объектом SP в группе.
                  Всё удаляем.
                  ExpandedWrap disabled
                    //Status = new Status() !!!Здесь может возникнуть исключение

                  Исключение может возникнуть везде.
                  Перехватим его и получим контекст.
                    Цитата ЫукпШ @
                    Исключение может возникнуть везде.
                    Перехватим его и получим контекст.


                    Нет, не везде. Это единственное место. Смотри, я там в общих чертах набросал реализацию. По моему как-раз то что тебе нужно

                    при исключении здесь нужно не контекст перехватывать, а выделенную память освободить, что и сделано
                    Сообщение отредактировано: Олег М -
                      Цитата Олег М @
                      По поводу memArray - диковатая довольно штука, особенно с учётом того, что этот флажок можно устанавливать независимо от указателя.

                      Если была акция по созданию массива объектов, тогда их правильно удалять
                      придётся операцией delete []. Это редкий вариант, но всё-же.
                      Установить флажок вручную - не сложное мероприятие.
                      ---
                      Мы же контролируем "вручную", что не делаем 2 равзные группы с одним
                      указателем на данные ? :huh:

                      Добавлено
                      Цитата Олег М @
                      Нет, не везде.

                      Везде.
                      Ты разименовываешь указатель (где-то), в результате сбоя аппаратных
                      средств значение казателя становится равным 0...
                        Цитата ЫукпШ @
                        Если была акция по созданию массива объектов, тогда их правильно удалять
                        придётся операцией delete []. Это редкий вариант, но всё-же.
                        Установить флажок вручную - не сложное мероприятие.


                        Тебе нужно удалять указатель так же, как он был создан (по-возможности, естеcтвенно). Этого можно достичь при помощи unique_ptr, как я тебе показал. Кроме того, так можно будет гарантировать, что память будет корректно освобождена при исключении в new.

                        На остальные исключения, аппаратные, можно здесь даже не закладываться.
                        Во-первых, такие исключения свидетельствуют о серьёзной ошибке в программе, линукс при этом просто падает (с одной стороны это плохо, с другой - дисциплинирует).
                        Во-вторых, они крайне маловероятны, в основном всё сводится к твоим исключениям и std::exception.
                        Сообщение отредактировано: Олег М -
                          Цитата Олег М @
                          Цитата ЫукпШ @
                          Если была акция по созданию массива объектов, тогда их правильно удалять
                          придётся операцией delete []. Это редкий вариант, но всё-же.
                          Установить флажок вручную - не сложное мероприятие.


                          Тебе нужно удалять указатель так же, как он был создан (по-возможности, естеcтвенно).

                          Да. Допустим, я создал его операцией new [].
                            Цитата ЫукпШ @
                            Да. Допустим, я создал его операцией new [].


                            Тогда тебе его нужно и удалять delete[], желательно гарантированно, без возможности изменить. Для этого лучше воспользоваться классом std::unique_ptr<T[]>, сохранить его функцию удаления и т.д.
                              Цитата Олег М @
                              Цитата ЫукпШ @
                              Да. Допустим, я создал его операцией new [].


                              Тогда тебе его нужно и удалять delete[], желательно гарантированно, без возможности изменить

                              Это я и делаю - и вообще, о чём разговор ?
                              Мне именно такой функционал нужен - я его делаю.
                              Тебе не нужен - не делай.
                                Цитата ЫукпШ @
                                Тебе не нужен - не делай.


                                Я и не делаю, как ты заметил. И тебе не рекомендую так делать. Но это исключительно рекомендации, решения принимаешь ты сам.
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (16) « Первая ... 7 8 [9] 10 11 ...  15 16 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0490 ]   [ 16 queries used ]   [ Generated: 18.07.25, 15:23 GMT ]