
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Страницы: (16) « Первая ... 7 8 [9] 10 11 ... 15 16 все ( Перейти к последнему сообщению ) |
Сообщ.
#121
,
|
|
|
Интернет-брокер Добавлено Цитата ЫукпШ @ Попробуем сначала. 1. Будем писать шаблонный класс SP - группа объектов указывает на какой-то объект в памяти. SP должен уметь создать группу, уничтожить группу и объект, присоединиться к группе, отсоединиться от группы. Обеспечить доступ к объекту. Желательно возможность модификации объекта как-нибудь по-проще. Что-то никак могу взять в толк, что именно требуется. Не доходит. А можешь как-то грубо накидать в виде классов, без потоков, чисто символически. Мне так проще понять будет. |
Сообщ.
#122
,
|
|
|
Цитата Олег М @ А можешь как-то грубо накидать в виде классов, Вот, сделал оба варианта. В многопоточном приложении проверил оба, но не запредельно подробно. Прикреплённый файл ![]() |
Сообщ.
#123
,
|
|
|
Цитата ЫукпШ @ Вот, сделал оба варианта. В многопоточном приложении проверил оба, но не запредельно подробно. Т.е. насколько я понял: - У тебя есть указатель и счётчик ссылок, 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; И дальше, по аналогии |
Сообщ.
#124
,
|
|
|
По поводу memArray - диковатая довольно штука, особенно с учётом того, что этот флажок можно устанавливать независимо от указателя.
Я бы тут сделал примерно так ![]() ![]() 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; }; |
Сообщ.
#125
,
|
|
|
Цитата Олег М @ Попробуем сначала. 1. Будем писать шаблонный класс SP - группа объектов указывает на какой-то объект в памяти. SP должен уметь создать группу, уничтожить группу и объект, присоединиться к группе, отсоединиться от группы. Обеспечить доступ к объекту. Желательно возможность модификации объекта как-нибудь по-проще. 2. Имеется счётчик ссылок. 3. Предполагаем волюнтаристским способом, что создание или уничтожение группы - потокобезопасно (ПБ). Поскольку оба действия предполагают наличие только одного объекта SP. Судя по коду, тебе наверное нужно что-то наподобие вот этого ![]() ![]() 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-функции заменяется достаточно легко - убираешь атомик и подставляешь вместо его методов и операторов соответствующие функции |
Сообщ.
#126
,
|
|
|
Цитата Олег М @ - Безопасно тебе нужно только удалять содержимое Status. Правильно? Нет. Если дело дошло до удаления или создания группы (экземпляр статус) значит объект SP - один единственный. И значит, что никакой потоко-безопасности сохранять не нужно. И это я сразу заявил в условиях. |
Сообщ.
#127
,
|
|
|
Цитата ЫукпШ @ Нет. Если дело дошло до удаления или создания группы (экземпляр статус) значит объект SP - один единственный. И значит, что никакой потоко-безопасности сохранять не нужно. Это и имелось ввиду - безопасно определить, что ссылок больше нет и удалить объект, ShPtrIntLockedTh<T>::DisConnectSlave. Так? |
Сообщ.
#128
,
|
|
|
Цитата Олег М @ Это и имелось ввиду - безопасно определить, что ссылок больше нет и удалить объект, ShPtrIntLockedTh<T>::DisConnectSlave. Так? Да. Если декремент сделан потоко-безопасно и в результате 0, значит работаем с последним объектом SP в группе. Всё удаляем. ![]() ![]() //Status = new Status() !!!Здесь может возникнуть исключение Исключение может возникнуть везде. Перехватим его и получим контекст. |
Сообщ.
#129
,
|
|
|
Цитата ЫукпШ @ Исключение может возникнуть везде. Перехватим его и получим контекст. Нет, не везде. Это единственное место. Смотри, я там в общих чертах набросал реализацию. По моему как-раз то что тебе нужно при исключении здесь нужно не контекст перехватывать, а выделенную память освободить, что и сделано |
Сообщ.
#130
,
|
|
|
Цитата Олег М @ По поводу memArray - диковатая довольно штука, особенно с учётом того, что этот флажок можно устанавливать независимо от указателя. Если была акция по созданию массива объектов, тогда их правильно удалять придётся операцией delete []. Это редкий вариант, но всё-же. Установить флажок вручную - не сложное мероприятие. --- Мы же контролируем "вручную", что не делаем 2 равзные группы с одним указателем на данные ? ![]() Добавлено Цитата Олег М @ Нет, не везде. Везде. Ты разименовываешь указатель (где-то), в результате сбоя аппаратных средств значение казателя становится равным 0... |
Сообщ.
#131
,
|
|
|
Цитата ЫукпШ @ Если была акция по созданию массива объектов, тогда их правильно удалять придётся операцией delete []. Это редкий вариант, но всё-же. Установить флажок вручную - не сложное мероприятие. Тебе нужно удалять указатель так же, как он был создан (по-возможности, естеcтвенно). Этого можно достичь при помощи unique_ptr, как я тебе показал. Кроме того, так можно будет гарантировать, что память будет корректно освобождена при исключении в new. На остальные исключения, аппаратные, можно здесь даже не закладываться. Во-первых, такие исключения свидетельствуют о серьёзной ошибке в программе, линукс при этом просто падает (с одной стороны это плохо, с другой - дисциплинирует). Во-вторых, они крайне маловероятны, в основном всё сводится к твоим исключениям и std::exception. |
Сообщ.
#132
,
|
|
|
Цитата Олег М @ Цитата ЫукпШ @ Если была акция по созданию массива объектов, тогда их правильно удалять придётся операцией delete []. Это редкий вариант, но всё-же. Установить флажок вручную - не сложное мероприятие. Тебе нужно удалять указатель так же, как он был создан (по-возможности, естеcтвенно). Да. Допустим, я создал его операцией new []. |
Сообщ.
#133
,
|
|
|
Цитата ЫукпШ @ Да. Допустим, я создал его операцией new []. Тогда тебе его нужно и удалять delete[], желательно гарантированно, без возможности изменить. Для этого лучше воспользоваться классом std::unique_ptr<T[]>, сохранить его функцию удаления и т.д. |
Сообщ.
#134
,
|
|
|
Цитата Олег М @ Цитата ЫукпШ @ Да. Допустим, я создал его операцией new []. Тогда тебе его нужно и удалять delete[], желательно гарантированно, без возможности изменить Это я и делаю - и вообще, о чём разговор ? Мне именно такой функционал нужен - я его делаю. Тебе не нужен - не делай. |
Сообщ.
#135
,
|
|
|
Цитата ЫукпШ @ Тебе не нужен - не делай. Я и не делаю, как ты заметил. И тебе не рекомендую так делать. Но это исключительно рекомендации, решения принимаешь ты сам. |