
Vyacheslav
25.10.2018
10:03:25

Constantine
25.10.2018
10:03:48

Vyacheslav
25.10.2018
10:03:50

Constantine
25.10.2018
10:04:00

Google

Vyacheslav
25.10.2018
10:04:50
Отойду на обед. У кого тоже обед - приятного аппетита.


Constantine
25.10.2018
10:08:34
Как только у вас начинаются shared_ptr у вас вылетает нормальное RAII, все обертывается на Maybe и вообще становится очень приятно программировать
И вот эта возникающая maybe-обертка в COM как раз проблема COM, а не структуры, к которой его подсоединяют
Потому что если структура выставляет четкое требование "объект внутри диалога никогда не переживет диалог", "порядок создания определяет порядок удаления" и "объект в невалидном состоянии не существует", у вас нет maybe-оберток и просто не бывает полувалидных объектов типа "диалог, который почему-то еще недоумер"

Timothy
25.10.2018
10:18:21

Ilia
25.10.2018
10:34:58

Igor
25.10.2018
10:54:56
Командой соответствующей
команда поиска это конечно шик, да
conan search openssl: None found. эээ. а ну да, он же по умолчанию в кэше только ищет.
conan search openssl -r all: None found. эээ. а ну да, там же нужно wildcard в референс пихать
conan search openssl/* -r all: None found. эээ. а ну да, он же регистрозависимый
conan search OpenSSL/* -r all: 9 found, hallelujah

Alex
25.10.2018
10:56:09

Igor
25.10.2018
10:56:09
вот эта штука иногда здорово спасает https://02jandal.github.io/conan_inquiry/

Google

Alex
25.10.2018
10:56:44
я прошёл эти квесты, но там дальше есть новые уровни :)
шикарно, спасибо за ссылку

Igor
25.10.2018
10:57:27

Alex
25.10.2018
10:58:52
У нужной мне либы проблемы с зависимостями, не нашлось нужной ей версии zlib. Наверное, это просто недоделанный пакет, написал в bincrafters issue на Github

Alexander
25.10.2018
10:59:34
Konstantin

Konstantin
25.10.2018
11:00:12
Да, его сейчас делают


Vyacheslav
25.10.2018
11:21:17
Как только у вас начинаются shared_ptr у вас вылетает нормальное RAII, все обертывается на Maybe и вообще становится очень приятно программировать
И вот эта возникающая maybe-обертка в COM как раз проблема COM, а не структуры, к которой его подсоединяют
"Начнём с того, что у COM нет проблем." -- проблемы могут появиться там, где его используют нарушая его правила. COM объект - это чисто shared_ptr модель, только счётчик ссылок не хранится инкапсулированно в отдельном участке динамической памяти, а хранится в самом объекте. Время жизни объекта определяется тем, как с ним работает клиент. Если клиент "отвалится", COM освободит ссылку на объект по таймауту. Подобная модель используется, например, в проброске C++ объектов в Lua, в C# и Java (Garbage Collector), в "правильном" TCP подключении, когда клиент закрывает подключение (по этикету звонящий вещает трубку первым). COM сам по себе ссылки на объект не удерживает, а проксирует работу клиента с ними на сервер.
В примере "объект внутри диалога никогда не переживает диалог" этому объекту достаточно держать строгую ссылку на диалог, а диалогу - слабую на объект, если сам объект - это COM-объект.
ИЛИ
Диалогу достаточно держать строгую ссылку на объект, если диалог - это COM-объект.
ИЛИ
Если объект - это COM-объект, то он может увеличивать счетчик ссылок диалога при увеличении своего счетчика ссылок и уменьшать при уменьшении. В этом случае, если явно хочется позвать delete (или объявить объект членом класса диалога), то нужно переопределить реализацию Release, чтобы при достижении 0 объектным счетчиком ссылок, не звался delete this;
В способах выше нет "полувалидных" объектов, но их нельзя явно убить по какому-то желанию/событию/самостоятельно. Нижний в иерархии объект должен быть выделен в динамической памяти или переживать старт-закрытие COM сервера.
Убить явно такой объект - это всё равно что закрыть сервером клиентское подключение, позвать free для переданного в функцию указателя и т.п.
#архитектура


Constantine
25.10.2018
11:23:01
"Начнём с того, что у COM нет проблем." -- проблемы могут появиться там, где его используют нарушая его правила. COM объект - это чисто shared_ptr модель, только счётчик ссылок не хранится инкапсулированно в отдельном участке динамической памяти, а хранится в самом объекте. Время жизни объекта определяется тем, как с ним работает клиент. Если клиент "отвалится", COM освободит ссылку на объект по таймауту. Подобная модель используется, например, в проброске C++ объектов в Lua, в C# и Java (Garbage Collector), в "правильном" TCP подключении, когда клиент закрывает подключение (по этикету звонящий вещает трубку первым). COM сам по себе ссылки на объект не удерживает, а проксирует работу клиента с ними на сервер.
В примере "объект внутри диалога никогда не переживает диалог" этому объекту достаточно держать строгую ссылку на диалог, а диалогу - слабую на объект, если сам объект - это COM-объект.
ИЛИ
Диалогу достаточно держать строгую ссылку на объект, если диалог - это COM-объект.
ИЛИ
Если объект - это COM-объект, то он может увеличивать счетчик ссылок диалога при увеличении своего счетчика ссылок и уменьшать при уменьшении. В этом случае, если явно хочется позвать delete (или объявить объект членом класса диалога), то нужно переопределить реализацию Release, чтобы при достижении 0 объектным счетчиком ссылок, не звался delete this;
В способах выше нет "полувалидных" объектов, но их нельзя явно убить по какому-то желанию/событию/самостоятельно. Нижний в иерархии объект должен быть выделен в динамической памяти или переживать старт-закрытие COM сервера.
Убить явно такой объект - это всё равно что закрыть сервером клиентское подключение, позвать free для переданного в функцию указателя и т.п.
#архитектура
Давайте обсуждать вопрос shared_ptr архитектуры безотносительно COM, OK?
> В примере "объект внутри диалога никогда не переживает диалог" этому объекту достаточно держать строгую ссылку на диалог, а диалогу - слабую на объект
Что должен сделать диалог, если weak в nullptr?
> Диалогу достаточно держать строгую ссылку на объект
Что должен делать объект, если диалога больше нет?


Vyacheslav
25.10.2018
11:25:50
Сейчас поясню.

Constantine
25.10.2018
11:26:48

Vyacheslav
25.10.2018
11:28:04

Constantine
25.10.2018
11:28:40
вы меня понимаете? :)

Vyacheslav
25.10.2018
11:44:04
Условие: объект A не переживает объект B.
Объект A создаётся в рамках жизни объекта B. Мы хотим передать ссылку на A во внешнюю среду.
Решение в рамках shared_ptr:
using namespace std;
class B : enable_shared_from_this {
public:
class A {
shared_ptr<B> strong_ref;
A(const shared_ptr<B>& b) : strong_ref(b) {}
}
private:
weak_ptr<A> _a;
B() = default;
public:
static shared_ptr<B> CreateB() {
return make_shared<B>();
}
shared_ptr<A> GetA() {
if (auto a = _a.lock())
return a;
auto a = make_shared<A>(shared_from_this());
_a = a;
return a;
}
}
P.S. с телефона я пишу код долго.
Перепутал A и B в условии. Поправил.

Constantine
25.10.2018
11:45:07

Vyacheslav
25.10.2018
11:45:26
Его нельзя интерпретировать двояко

Constantine
25.10.2018
11:48:18
Его нельзя интерпретировать двояко
Если я ничего не путаю, ваш пример это optional поле класса, хранящее сильную ссылку на класс, правильно?
Это как раз приводит к ситуации полумертвого объекта самого класса - в этом случае предполагается, что класс всегда находится в некотором полноценном состоянии и внешние факторы на это не влияют

Google

Vyacheslav
25.10.2018
11:49:24
Или вы хотите, чтобы время жизни А и В совпадало?

Constantine
25.10.2018
11:50:22
Это как раз модель что диалог не умер когда стек раскрутился до вызвавшего диалог

Vyacheslav
25.10.2018
11:50:47

Constantine
25.10.2018
11:52:01

Vyacheslav
25.10.2018
11:52:02
Например, через notify уведомлять о своём уничтожении.

Constantine
25.10.2018
11:53:03

Vyacheslav
25.10.2018
11:53:03
Если В требуется файл, а А требуется В, то всё норм

Constantine
25.10.2018
11:54:55
Не вижу проблемы с открытым файлом.
Вот представьте, у вас В это таска, которая занимается отложенной записью каких-то данных на диск и держит блокировку на файл
Вы передали её в поток-исполнитель, который её прибил (дропнул свою ссылку) по завершении, но на самом деле файл, возможно, остался открытым
Правильно ли это?

Vyacheslav
25.10.2018
11:55:56

Constantine
25.10.2018
11:57:36

Vyacheslav
25.10.2018
11:57:47
Проблема держания кем-то ссылки на А, когда поток хочет дождаться уничтожения В -- не проблема классов А и В.

Constantine
25.10.2018
11:58:04
В момент завершения таски ссылок на А, конечно, быть не должно

Vyacheslav
25.10.2018
11:58:53

Constantine
25.10.2018
11:59:09

Google

Vyacheslav
25.10.2018
11:59:40

Constantine
25.10.2018
12:00:10

Vyacheslav
25.10.2018
12:00:42

Constantine
25.10.2018
12:00:44
Вот это типичный RAII класс
SuperB на самом деле это почти в точности В

Vyacheslav
25.10.2018
12:01:03
Можно ещё рекурсивным мьютексом эту штуку заменить

Constantine
25.10.2018
12:01:40

Vyacheslav
25.10.2018
12:01:46
SuperB - это хотелка потока прибить B

Constantine
25.10.2018
12:02:03
Для SuperB можно применять любой метод В
Вся разница логики лежит в одной крохотной части поведения

Vyacheslav
25.10.2018
12:03:32
Кстати, shared_ptr чем-то похож на такой SuperB. Также объект на стеке, но он не гарантирует освобождения объекта на который указывает.

Constantine
25.10.2018
12:03:55
И очень не похож одновременно. SuperB как раз класс типа RAII, это прямое управление владением

Vyacheslav
25.10.2018
12:04:38
Если требуется подчеркнуть, что в момент завершения такси В должен быть разрушен, то достаточно проверить факт его разрушения после отпускания shared_ptr. И если это не так, то кинуть исключение.

Constantine
25.10.2018
12:04:59

Vyacheslav
25.10.2018
12:05:20
Консенсус?
:)

Constantine
25.10.2018
12:05:48

Google

Constantine
25.10.2018
12:06:28
На самом деле все, что вы сделаете, когда напишете версию с assert это буквально то же самое, что написать
struct B {
A a;
};
С точностью до того, что вы умеете рантайм-проверку делать

Vyacheslav
25.10.2018
12:07:07

Constantine
25.10.2018
12:07:34

Vyacheslav
25.10.2018
12:07:52
Таска же владеет В, так?

Constantine
25.10.2018
12:08:39
*На В
На самом деле на А. Вы попытались удалить В

Vyacheslav
25.10.2018
12:09:06
Не суть

Constantine
25.10.2018
12:09:26

Vyacheslav
25.10.2018
12:10:00

Constantine
25.10.2018
12:10:14
Например, класть ему новые таски в очередь

Vyacheslav
25.10.2018
12:10:46
А потом перейдём к новым условиям

Constantine
25.10.2018
12:12:16
Внешнее поле создается, например, через обмен с using guard_ptr = std::unique_ptr<VirtuallyDestructible> который записывается в поле отдавшего класса
Т.е.
A& a_ref(guard_ptr a_guard) {
a_guard_ = std::move(a_guard);
return a;
}

Vyacheslav
25.10.2018
12:14:17

Constantine
25.10.2018
12:15:11

Vyacheslav
25.10.2018
12:15:17