Re[13]: Исповедь C++ника
От: B0FEE664  
Дата: 24.12.20 16:19
Оценка:
Здравствуйте, Умака Кумакаки, Вы писали:

BFE>>Зачем? К тому же, если эти данные нужны, то их можно положить в то, что скрывается за void*.

УК>Затем, что во многих ситуациях я хочу оперировать с данными контрола в коллбеке ивента,
Для этого есть void*

УК>например сделать кнопку неактивной,

Вы собираетесь делать кнопку неактивной в callback в момент её нажатия? Вы понимаете, к чему это скорее всего приведёт?

УК> получить текст из едитбокса,

Зачем для этого указатель на кнопку?

УК> отписаться от события итд итп.

Т.е. вы собираетесь вызвать Button::RemoveOnButtonPress() метод внутри callback'а? Я вас правильно понимаю? Вы хорошо подумали?

УК> Положить можно в void, только зачем заставлять пользователя библиотеки реализовывать стандартную для любой UI библиотеки машинерию?

Заставлять не надо и это не стандартная схема.

BFE>>Вообще-то void* — это нечто прямо противоположное к прозрачному, это полностью скрытые данные или интерфейсы о которых ничего не известно.

УК>ты следи за контекстом, прозрачный относилось к коду. И использование void* как пользовательского контекста это вообще практика со времён зарождения си и коллбеков.
Вот именно, что C, а не C++. В С++ всё иначе должно быть.

УК>>>Если честно, твои вопросы меня озадачивают, ты вообще сколько кода читал/писал за свою жизнь?

BFE>>Много. Сотни мегабайтов, наверное.
УК>А что не гигабайтов? Ты похоже далёк от разработки совсем. Судя по всему, что тебя удивляют стандартные UI паттерны, которые есть в любой UI библиотеке, начиная от MFC и заканчивая HTML DOM с его addEventListener, вероятно ты не настоящий сварщик.

Меня эти "стандартные" UI паттерны не удивляют, мне от них плакать хочется.

BFE>>А вот вы пишите, что это тривиальная реализация. Тогда может объясните, зачем там динамический список обработчиков? Ведь такой список обработчиков имеет смысл только при динамическом изменении этого списка, так как иначе можно просто задать один статический обработчик в котором последовательно и явно в коде написать вызовы всех тех кто хочет быть подписан на эти вызовы. Т.е. один callback в котором просто вписаны вызовы всех других. Если же нужен именно динамический список, тогда может быть вы можете указать на задачу, где у кнопки в рантайме меняется список обработчиков у одной и той же кнопки, причём так, что список этих обработчиков не может быть составлен заранее?


УК>Ты прикалываешься? Это же очевидно UI библиотека, у неё не может быть статических обработчиков, так как они задаются пользователем библиотеки (в рантайме). Боже, какой же ты дремучий.


Нет, вы не обзывайтесь, а давайте объясните зачем там список и почему нельзя обойтись одним callback'ом. Особенно мне интересно, что, по вашему мнению, будет при вызове метода RemoveOnButtonPress изнутри callback'а (или как вы там собираетесь отписаться от события)?
И каждый день — без права на ошибку...
Re[14]: Исповедь C++ника
От: Умака Кумакаки Ниоткуда  
Дата: 24.12.20 16:45
Оценка: :)
Здравствуйте, B0FEE664, Вы писали:

извини, но я уже сделал вывод что ты просто тупой и не в коня корм, не хочу на тебя тратить время, попробуй сам написать UI библиотеку на C++, может быть что-то прояснится.
нормально делай — нормально будет
Re[15]: Исповедь C++ника
От: B0FEE664  
Дата: 24.12.20 17:58
Оценка:
Здравствуйте, Умака Кумакаки, Вы писали:

УК>извини, но я уже сделал вывод что ты просто тупой и не в коня корм, не хочу на тебя тратить время, попробуй сам написать UI библиотеку на C++, может быть что-то прояснится.


Жаль, очень жаль, что на мои простые вопросы нет никаких конструктивных ответов.
И каждый день — без права на ошибку...
Re[14]: Исповедь C++ника
От: Lexey Россия  
Дата: 24.12.20 22:03
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Зачем? К тому же, если эти данные нужны, то их можно положить в то, что скрывается за void*.

УК>>Затем, что во многих ситуациях я хочу оперировать с данными контрола в коллбеке ивента,
BFE>Для этого есть void*

void* для этого хреново подходит, ибо один и тот же обработчик может обрабатывать несколько кнопок. Нет, можно, конечно, при подписке передавать разные контексты, но потом их придется разруливать внутри обработчика, что явно не упростит его код. Данные об источнике (кнопке) и контексте обработчика, действительно, удобнее передавать раздельно.

УК>>например сделать кнопку неактивной,

BFE>Вы собираетесь делать кнопку неактивной в callback в момент её нажатия? Вы понимаете, к чему это скорее всего приведёт?

Вполне вероятно, что ни к чему плохому. Возможный сценарий: нажали кнопку Abort, в обработчике мы ее деактивируем и запускаем диалог с прогрессом отката.

УК>> отписаться от события итд итп.

BFE>Т.е. вы собираетесь вызвать Button::RemoveOnButtonPress() метод внутри callback'а? Я вас правильно понимаю? Вы хорошо подумали?

Для кнопок это несколько странный сценарий, но, гипотетически возможный. Например, нужно в обработчике дождаться нажатия нескольких кнопок (в любом порядке). Получили одно нажатие, отписались, ждем остальных. Если же забыть про кнопки, то это вполне типичный сценарий ожидания результатов нескольких операций.

УК>> Положить можно в void, только зачем заставлять пользователя библиотеки реализовывать стандартную для любой UI библиотеки машинерию?

BFE>Заставлять не надо и это не стандартная схема.

Схема вполне стандартная.

BFE>>>Вообще-то void* — это нечто прямо противоположное к прозрачному, это полностью скрытые данные или интерфейсы о которых ничего не известно.


Ничего неизвестно на стороне, генерирующей события. Но, на ней и не нужно ничего знать про внутреннее устройство того, что лежит под void*.

BFE>Вот именно, что C, а не C++. В С++ всё иначе должно быть.


В случае UI соглашусь. Но, подобные схемы не только для него используются. И, иногда, абстракции типа std::function или интерфейса с виртуальным методом в качестве колбэка могут быть слишком дороги по сравнению с обычной функцией, принимающей void*.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[12]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 25.12.20 01:24
Оценка:
Здравствуйте, smeeld, Вы писали:

>>Т.к. в list-е каждый элемент -- это динамически созданный объект, удаление которого всяко дороже, чем сдвиг нескольких соседей в vector-е.


S>Если размеры vector-а — миллионы, и это тяжёлые объекты, которые даже мувятся рядом операций копирования, то сколько будет шуршать такой сдвиг?


Да эти некоторые представители профессии уже неоднократно проявили себя. Про устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node, они не слыхали. Они ж не "стреляют из пушки по воробьям". И весьма вероятно, что хеш от хипа не отличают, но зато мастурбируют на меташаблоны буста.
Re[13]: Исповедь C++ника
От: so5team https://stiffstream.com
Дата: 25.12.20 06:35
Оценка:
Здравствуйте, Тёмчик, Вы писали:

>>>Т.к. в list-е каждый элемент -- это динамически созданный объект, удаление которого всяко дороже, чем сдвиг нескольких соседей в vector-е.


S>>Если размеры vector-а — миллионы, и это тяжёлые объекты, которые даже мувятся рядом операций копирования, то сколько будет шуршать такой сдвиг?


Тё>Про устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node, они не слыхали. Они ж не "стреляют из пушки по воробьям".


Тёмчик, а какое это все имеет отношение к обсуждению уместности применения std::list вместо std::vector?

Тё>И весьма вероятно, что хеш от хипа не отличают, но зато мастурбируют на меташаблоны буста.


Зачем нам шаблоны какого-то Boost-а, если у нас своих полно?
Re[11]: Исповедь C++ника
От: CreatorCray  
Дата: 25.12.20 09:33
Оценка:
Здравствуйте, so5team, Вы писали:

S>Да ладно. Такое обычно живет в библиотеках и используется для решения очень специфических задач.

Ну разишо.
В любом случае такая трёхэтажность может быть оправдана только если у более простого кода практический выхлоп получается хуже. Т.е. код будет медленнее или более ресурсоёмкий.
Код пишется и оформляется для людей, машине всё равно.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[14]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 25.12.20 10:28
Оценка: :))
Здравствуйте, so5team, Вы писали:

S>Тёмчик, а какое это все имеет отношение к обсуждению уместности применения std::list вместо std::vector?

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

S>Зачем нам шаблоны какого-то Boost-а, если у нас своих полно?

Ну так а я про то, что мазохисты-сектанты с верой, что компилятор C++ из говна O(n*n) сделает ракету.

О чём с фанатиками разговаривать. И конторы плюсные поэтому специфические.
Re[15]: Исповедь C++ника
От: so5team https://stiffstream.com
Дата: 25.12.20 12:44
Оценка: +1
Здравствуйте, Тёмчик, Вы писали:

S>>Тёмчик, а какое это все имеет отношение к обсуждению уместности применения std::list вместо std::vector?

Тё>Блин, так это ж говнокод, что там обсуждать

Вы не знаете ни кто это писал, ни когда, ни зачем, ни в каких условиях. Но авторитетно заявляете про говнокод. Аргументировать можете?

Тё>какой сорт говна лучше- через список или массив.


Использование списка, массива или какой-либо другой структуры для хранения подписок -- это более чем принципиальный момент. Скажем, если "возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node", то vector для подписок будет не самым лучшим выбором. А при использовании list-а у вас будет оверхед по памяти и отсутствие локальности данных.

Но хватит зубы заговаривать, повторяю вопрос: каким боком здесь "устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node"?

Тё>Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


На какую именно?

S>>Зачем нам шаблоны какого-то Boost-а, если у нас своих полно?

Тё>Ну так а я про то, что мазохисты-сектанты с верой, что компилятор C++ из говна O(n*n) сделает ракету.

Ничего не понял, что сказать-то хотели?

Тё>О чём с фанатиками разговаривать. И конторы плюсные поэтому специфические.


Пока что единственный фанатик здесь вы. Фанатично верите в каких-то абстрактных C++ников.
Re[15]: Исповедь C++ника
От: AleksandrN Россия  
Дата: 25.12.20 13:59
Оценка:
Здравствуйте, Тёмчик, Вы писали:

Тё>Блин, так это ж говнокод, что там обсуждать какой сорт говна лучше- через список или массив. Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


Молодец. Ты уже всех убедил, что всё говнокод, кроме того, что ты написал, а ты — гений. Так просвети всех, пошли всех на гитхаб, дабы узрели твой код гениальный и осознали серость и убогость свою.
Re[16]: Исповедь C++ника
От: Dym On Россия  
Дата: 25.12.20 14:04
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN> Так просвети всех, пошли всех на гитхаб, дабы узрели твой код гениальный и осознали серость и убогость свою.

Не-не-не, не всяк, кто узреет код Темки сможет выжить, неподготовленного джуна, его сияющий код может вообще испепелить. Я бы не рискнул вот ссылки просить
Счастье — это Glück!
Re[15]: Исповедь C++ника
От: landerhigh Пират  
Дата: 25.12.20 21:58
Оценка:
Здравствуйте, Тёмчик, Вы писали:

Тё>Блин, так это ж говнокод, что там обсуждать какой сорт говна лучше- через список или массив. Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


Тема, ты только что заявил, что ты простейший колбек не сможешь реализовать без "библиотеки событийной модели".
www.blinnov.com
Re[16]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 26.12.20 02:15
Оценка: :)))
Здравствуйте, so5team, Вы писали:

S>Использование списка, массива или какой-либо другой структуры для хранения подписок -- это более чем принципиальный момент. Скажем, если "возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node", то vector для подписок будет не самым лучшим выбором. А при использовании list-а у вас будет оверхед по памяти и отсутствие локальности данных.

Попытаюсь объяснить упёртому...
Ну смотри — удаление подписки. Как ты её собрался искать в контейнере? Какова стоимость?

S>оверхед по памяти и отсутствие локальности данных

Ты это серьёзно сейчас? Из кривых тормозных кусков кода ты готов замерить оверхед и локальность данных?

S>Но хватит зубы заговаривать, повторяю вопрос: каким боком здесь "устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node"?



https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation


class Node<T> {
    T *object;
    Node<T> *prev
    Node<T> *next;
}

interface Subscription {
    void unsubscribe();
}

class SubscriptionImpl: Subscription {
    
    Node *node;
    
    void unsubscribe() {
        node.prev.next = node.next;
        node.next.prev = node.prev;
        node.prev = node.next = null;
    }
}


Сложность удаления O(1). Сложность добавления в конец либо в начало (по вкусу) O(1).



Тё>>Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


S>На какую именно?

http://reactivex.io/RxCpp/
http://reactivex.io/RxCpp/rx-publish_8hpp.html



S>>>Зачем нам шаблоны какого-то Boost-а, если у нас своих полно?

Тё>>Ну так а я про то, что мазохисты-сектанты с верой, что компилятор C++ из говна O(n*n) сделает ракету.

S>Ничего не понял, что сказать-то хотели?


Тё>>О чём с фанатиками разговаривать. И конторы плюсные поэтому специфические.


S>Пока что единственный фанатик здесь вы. Фанатично верите в каких-то абстрактных C++ников.

Одного из этих "отдельных представителей профессии" ты можешь увидеть в зеркале.
Re[17]: Исповедь C++ника
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 26.12.20 02:39
Оценка:
Здравствуйте, Тёмчик, Вы писали:

Тё>Сложность удаления O(1). Сложность добавления в конец либо в начало (по вкусу) O(1).


Я не знаю что у вас там в JS, но в языках близких к железу О-нотация не работает на маленьких объемах данных из за промахов по кэшу. О чем, собственно, тут и говорят. Вспоминай базу
Re[18]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 26.12.20 03:25
Оценка: +1 -4 :)
Здравствуйте, kaa.python, Вы писали:

KP>Я не знаю что у вас там в JS, но в языках близких к железу О-нотация не работает на маленьких объемах данных из за промахов по кэшу. О чем, собственно, тут и говорят. Вспоминай базу


Точно верующий. В си и два плюса его пророков
Re[17]: Исповедь C++ника
От: so5team https://stiffstream.com
Дата: 26.12.20 05:24
Оценка: +1 -1 :)
Здравствуйте, Тёмчик, Вы писали:

Тё>Ну смотри — удаление подписки. Как ты её собрался искать в контейнере? Какова стоимость?


Зависит от обстоятельств. К которым мы перейдем ниже, там где фрагменты кода появятся.

S>>оверхед по памяти и отсутствие локальности данных

Тё>Ты это серьёзно сейчас?

Гораздо более серьезно, чем когда вы заявляете, что C++ не используется для рилтайма.

Тё>Из кривых тормозных кусков кода ты готов замерить оверхед и локальность данных?


Как бы когда жизнь заставляет, то приходится замерять. Вне зависимости от качества кода. Более того, чем ниже качество, тем актуальнее становятся замеры.

S>>Но хватит зубы заговаривать, повторяю вопрос: каким боком здесь "устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node"?


Тё>https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation



Тё>
Тё>class Node<T> {
Тё>    T *object;
Тё>    Node<T> *prev
Тё>    Node<T> *next;
Тё>}

Тё>interface Subscription {
Тё>    void unsubscribe();
Тё>}

Тё>class SubscriptionImpl: Subscription {
    
Тё>    Node *node;
    
Тё>    void unsubscribe() {
Тё>        node.prev.next = node.next;
Тё>        node.next.prev = node.prev;
Тё>        node.prev = node.next = null;
Тё>    }
Тё>}


Тё>


Да уж, так откровенно расписаться в незнаниях C++... Это нужно постараться. Хотя, возможно, когда вы еще имели дело с C++, вам даже C++98 был недоступен.

Ибо в C++ Node<T> хранил бы экземпляр T не по указателю, а по значению. А то у вас получится по две аллокации на объект в списке: первая для самого T, вторая для Node<T>.

Кроме того, приведенный выше код можно считать документально зафиксированным подтверждением того, что местный Тёмчик говнокодер, неспособный в простейшие структуры данных. Ибо такая наивная реализация изъятия элемента из двусвязного списка без проверки на null значений node.prev/node.next -- это про*б сравнимый с неспособностью развернуть строку. Тёмчик, почему меня не удивляет факт того, что вы говнокодер?

Тё>Сложность удаления O(1). Сложность добавления в конец либо в начало (по вкусу) O(1).


А теперь давайте по сути. Допустим, у вас есть что-то вроде:
template<typename T> class Node {
  T value_;
  Node<T> * prev_;
  Node<T> * next_;
};

class Subscription {
  Node<T> * item_;
  ...
};


В качестве T у нас POD с двумя указателями.

Итак, нужно хранить два указателя. Для чего нам потребуется еще три указателя (два в Node, один в Subscription). Плюс добавим сюда тот факт, что Node будет аллоцироваться как отдельный объект. Т.е., скорее всего, ему должен предшествовать какой-то непустой memory-control-block + Node должен быть соответствующим образом выровнен (не будем сейчас брать вырожденные случаи с супер-пупер аллокаторами, которые не нуждаются в MCB и определяют принадлежность куска памяти по значению указателя). Скорее всего получится, что оверхед на хранение информации в списке будет раза эдак в два.

Далее, если пописчиков немного (не более десятка), то на современных процессорах тупой линейный поиск по маленькому (но непрерывному) вектору с последующим изъятием, будет эффективнее, чем скакание по разным кускам памяти для модификации соседних элементов в списке.

Далее, можно коснуться вопроса эргономики. Если у нас появляется объект Subscription, то его нужно будет хранить. Что далеко не всегда удобно. Бывают случаи (и таких случаев, могу утверждать из собственного опыта, немало) когда все, что нужно для отписки -- это указатель на сам callback. Даже не обязательно значение opaque-pointer-а, который при подписке связывается с callback-ом.

Если достаточно всего лишь указателя на callback, то хранение для каждой подписки Subscription -- это дополнительная головная боль. Особенно в C++, где ничего не защищает от обращения к повисшим указателям. Использовали экземпляр subscription для отписки один раз, а потом, по ошибке, сделали отписку повторно. И что будет в итоге? Хорошо, если при первой отписке значение в Subscription::item_ занулили. А если нет? Тут ведь и на ABA проблему можно нарваться.

Так что, как бы вам не привычно было бы видеть объект Subscription, в разных ситуациях привлекательность этого подхода может быть ну совершенно разной. Включая и "ниже плинтуса".

Тё>>>Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


S>>На какую именно?

Тё>http://reactivex.io/RxCpp/
Тё>http://reactivex.io/RxCpp/rx-publish_8hpp.html

Ок, спасибо. Посмотрю.

Тё>Одного из этих "отдельных представителей профессии" ты можешь увидеть в зеркале.


Для аргумента "сам дурак" вы что-то слишком сильно щеки надули.
Re[18]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 26.12.20 06:57
Оценка: +1
Здравствуйте, so5team, Вы писали:

Тё>>Ну смотри — удаление подписки. Как ты её собрался искать в контейнере? Какова стоимость?


S>Зависит от обстоятельств. К которым мы перейдем ниже, там где фрагменты кода появятся.

Не юли.

S>>>оверхед по памяти и отсутствие локальности данных

Тё>>Ты это серьёзно сейчас?

S>Гораздо более серьезно, чем когда вы заявляете, что C++ не используется для рилтайма.

Я заявлял, что в ядре не место C++. Именно полноценному C++, ибо C-с-классами не является полноценным C++ в понимании стандарта C++.

Тё>>Из кривых тормозных кусков кода ты готов замерить оверхед и локальность данных?


S>Как бы когда жизнь заставляет, то приходится замерять. Вне зависимости от качества кода. Более того, чем ниже качество, тем актуальнее становятся замеры.

И часто вас жизнь заставляет замерять оверхед на 10 элементах?

S>>>Но хватит зубы заговаривать, повторяю вопрос: каким боком здесь "устройство цикличного списка и возможность возвращать обьект Subscription с методом unsubscribe и внутри ссылкой на node"?


Тё>>https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation



Тё>>
Тё>>class Node<T> {
Тё>>    T *object;
Тё>>    Node<T> *prev
Тё>>    Node<T> *next;
Тё>>}

Тё>>interface Subscription {
Тё>>    void unsubscribe();
Тё>>}

Тё>>class SubscriptionImpl: Subscription {
    
Тё>>    Node *node;
    
Тё>>    void unsubscribe() {
Тё>>        node.prev.next = node.next;
Тё>>        node.next.prev = node.prev;
Тё>>        node.prev = node.next = null;
Тё>>    }
Тё>>}


Тё>>


S>Да уж, так откровенно расписаться в незнаниях C++... Это нужно постараться. Хотя, возможно, когда вы еще имели дело с C++, вам даже C++98 был недоступен.


S>Ибо в C++ Node<T> хранил бы экземпляр T не по указателю, а по значению. А то у вас получится по две аллокации на объект в списке: первая для самого T, вторая для Node<T>.

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

S>Кроме того, приведенный выше код можно считать документально зафиксированным подтверждением того, что местный Тёмчик говнокодер, неспособный в простейшие структуры данных. Ибо такая наивная реализация изъятия элемента из двусвязного списка без проверки на null значений node.prev/node.next -- это про*б сравнимый с неспособностью развернуть строку. Тёмчик, почему меня не удивляет факт того, что вы говнокодер?


Чувачелло, величина твоего невежества зашкаливает. Но я же привёл ссылку. Сложно прочитать?

Тё>>https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation



Тё>>Сложность удаления O(1). Сложность добавления в конец либо в начало (по вкусу) O(1).


S>А теперь давайте по сути. Допустим, у вас есть что-то вроде:

S>
S>template<typename T> class Node {
S>  T value_;
S>  Node<T> * prev_;
S>  Node<T> * next_;
S>};

S>class Subscription {
S>  Node<T> * item_;
S>  ...
S>};
S>

Что за долбанутые наименования с подчёркиванием на конце.

S>В качестве T у нас POD с двумя указателями.


S>Итак, нужно хранить два указателя. Для чего нам потребуется еще три указателя (два в Node, один в Subscription). Плюс добавим сюда тот факт, что Node будет аллоцироваться как отдельный объект. Т.е., скорее всего, ему должен предшествовать какой-то непустой memory-control-block + Node должен быть соответствующим образом выровнен (не будем сейчас брать вырожденные случаи с супер-пупер аллокаторами, которые не нуждаются в MCB и определяют принадлежность куска памяти по значению указателя). Скорее всего получится, что оверхед на хранение информации в списке будет раза эдак в два.


S>Далее, если пописчиков немного (не более десятка), то на современных процессорах тупой линейный поиск по маленькому (но непрерывному) вектору с последующим изъятием, будет эффективнее, чем скакание по разным кускам памяти для модификации соседних элементов в списке.

Если пописчиков немного, то не стоит заморачиваться на алгоритмическую сложность.

S>Далее, можно коснуться вопроса эргономики. Если у нас появляется объект Subscription, то его нужно будет хранить. Что далеко не всегда удобно. Бывают случаи (и таких случаев, могу утверждать из собственного опыта, немало) когда все, что нужно для отписки -- это указатель на сам callback. Даже не обязательно значение opaque-pointer-а, который при подписке связывается с callback-ом.

Кто управляет временем жизни callback?

S>Если достаточно всего лишь указателя на callback, то хранение для каждой подписки Subscription -- это дополнительная головная боль. Особенно в C++, где ничего не защищает от обращения к повисшим указателям.

У хорошего плюсника не бывает тухлых указателей. Вы к таким определённо не относитесь.

S> Использовали экземпляр subscription для отписки один раз, а потом, по ошибке, сделали отписку повторно. И что будет в итоге?

В итоге будет nullptr и это правильно. Ибо кривые руки повторно-вызывальщиков отписок, релизов, диспозов и прочих делетов нужно испрямнять жёстко и без церемоний.

S>Так что, как бы вам не привычно было бы видеть объект Subscription, в разных ситуациях привлекательность этого подхода может быть ну совершенно разной. Включая и "ниже плинтуса".


Тё>>>>Посмотри на реализацию событийной модели здорового человека- может что-нибудь новое для себя узнаешь.


S>>>На какую именно?

Тё>>http://reactivex.io/RxCpp/
Тё>>http://reactivex.io/RxCpp/rx-publish_8hpp.html

S>Ок, спасибо. Посмотрю.

Посмотри. Потом как посмотришь, можно будет предметно обсуждать, говно код та наивная копипаста событийной модели, или нет.
Re[19]: Исповедь C++ника
От: so5team https://stiffstream.com
Дата: 26.12.20 07:31
Оценка: +1
Здравствуйте, Тёмчик, Вы писали:

Тё>>>Ну смотри — удаление подписки. Как ты её собрался искать в контейнере? Какова стоимость?


S>>Зависит от обстоятельств. К которым мы перейдем ниже, там где фрагменты кода появятся.

Тё>Не юли.

Сперва прочитайте то, что вам пишут, потом уже отвечайте.

S>>Гораздо более серьезно, чем когда вы заявляете, что C++ не используется для рилтайма.

Тё>Я заявлял, что в ядре не место C++. Именно полноценному C++, ибо C-с-классами не является полноценным C++ в понимании стандарта C++.

Вы заявили следующее (http://rsdn.org/forum/job/7907304.1):
Автор: Тёмчик
Дата: 17.12.20


> Реалтаймовые системы не на плюсах делают.


Все ходы записаны.

Тё>И часто вас жизнь заставляет замерять оверхед на 10 элементах?


Нет. Но бывает.

S>>Ибо в C++ Node<T> хранил бы экземпляр T не по указателю, а по значению. А то у вас получится по две аллокации на объект в списке: первая для самого T, вторая для Node<T>.

Тё>Ты в курсе, что есть указатель на T, в данном случае? Может быть, это указатель на какой-то родительский объект или другую подписку, которого можно дёрнуть для оповещения об изменениях. Может быть, его и заполнять необязательно.

Тёмчик, давайте говорить о примере от B0FEE664. В котором под T можно подразумевать только std::pair<OnPress, void*>. Если вы хотите ввести в обсуждение еще что-то, то потрудитесь это описать, чтобы люди понимали, о чем речь.

Тё>Чувачелло, величина твоего невежества зашкаливает. Но я же привёл ссылку. Сложно прочитать?

Тё>

Тё>>>https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation


Т.е. вы для хранения списка подписок предлагаете хранить еще и специальный sentinel node?

Тё>Если пописчиков немного, то не стоит заморачиваться на алгоритмическую сложность.


Если вы еще не заметили, то речь идет не про алгоритмическую сложность, а о стоимости по памяти и времени исполнения. В случаях, когда подписчиков немного.

Тё>Кто управляет временем жизни callback?


Подписчик.

S>>Если достаточно всего лишь указателя на callback, то хранение для каждой подписки Subscription -- это дополнительная головная боль. Особенно в C++, где ничего не защищает от обращения к повисшим указателям.

Тё>У хорошего плюсника не бывает тухлых указателей. Вы к таким определённо не относитесь.

Без разницы к каким вы меня относите. Суть в том, что такая проблема есть. И решений, которые ее провоцируют, следует избегать. Тогда будет не важно, хороший плюсник работает с кодом или нет.

S>> Использовали экземпляр subscription для отписки один раз, а потом, по ошибке, сделали отписку повторно. И что будет в итоге?

Тё>В итоге будет nullptr и это правильно. Ибо кривые руки повторно-вызывальщиков отписок, релизов, диспозов и прочих делетов нужно испрямнять жёстко и без церемоний.

На словах все герои. Только вот если у вас отписка работает через поиск (по указателю на callback или по какому-то уникальному Id), то она оказывается более устойчивой к подобным ошибкам.

Кроме того, в C++ объекты по умолчанию копируются. Т.е. если есть:
class Subscription {
  Node * node_;
public:
  ...
  void unsubscribe() {
    if(node_) {
      ...
      node_ = nullptr;
    }
  }
};

То потребуется еще позаботится о том, чтобы объекты Subscription не копировались. Потому что зануление node_ в копии никак не скажется на исходном объекте. А до C++11 нормальных средств для этого в языке не было (а код от B0FEE664 явно написан для C++98).
Re[19]: Исповедь C++ника
От: so5team https://stiffstream.com
Дата: 26.12.20 08:01
Оценка:
Здравствуйте, Тёмчик, Вы писали:

Тё>>>http://reactivex.io/RxCpp/

Тё>>>http://reactivex.io/RxCpp/rx-publish_8hpp.html

S>>Ок, спасибо. Посмотрю.

Тё>Посмотри. Потом как посмотришь, можно будет предметно обсуждать, говно код та наивная копипаста событийной модели, или нет.

Если заглянуть сюда (https://github.com/ReactiveX/RxCpp/blob/master/Rx/v2/src/rxcpp/rx-subscription.hpp), то точно можно сказать, что для каких-то простых задач RxCpp будет 100% "из пушки по воробьям".
Re[20]: Исповедь C++ника
От: Тёмчик Австралия жж
Дата: 26.12.20 09:35
Оценка: -1 :))
Здравствуйте, so5team, Вы писали:

Тё>>>>Ну смотри — удаление подписки. Как ты её собрался искать в контейнере? Какова стоимость?


S>>>Зависит от обстоятельств. К которым мы перейдем ниже, там где фрагменты кода появятся.

Тё>>Не юли.

S>Сперва прочитайте то, что вам пишут, потом уже отвечайте.


OMG да я понял, что вы давно слились, когда запели про "10 подписок".

S>>>Гораздо более серьезно, чем когда вы заявляете, что C++ не используется для рилтайма.

Тё>>Я заявлял, что в ядре не место C++. Именно полноценному C++, ибо C-с-классами не является полноценным C++ в понимании стандарта C++.

S>Вы заявили следующее (http://rsdn.org/forum/job/7907304.1):
Автор: Тёмчик
Дата: 17.12.20

Реалтайм бывает soft и hard. Soft вообще похрен на чём делать, а для hard плюсы не подходят (если не рассматривать C с классами).

>> Реалтаймовые системы не на плюсах делают.


S>Все ходы записаны.


Тё>>И часто вас жизнь заставляет замерять оверхед на 10 элементах?


S>Нет. Но бывает.


S>>>Ибо в C++ Node<T> хранил бы экземпляр T не по указателю, а по значению. А то у вас получится по две аллокации на объект в списке: первая для самого T, вторая для Node<T>.

Тё>>Ты в курсе, что есть указатель на T, в данном случае? Может быть, это указатель на какой-то родительский объект или другую подписку, которого можно дёрнуть для оповещения об изменениях. Может быть, его и заполнять необязательно.

S>Тёмчик, давайте говорить о примере от B0FEE664. В котором под T можно подразумевать только std::pair<OnPress, void*>. Если вы хотите ввести в обсуждение еще что-то, то потрудитесь это описать, чтобы люди понимали, о чем речь.

Почему у вас onpress в типе? Почему у вас void*? Вы что, про статическую типизацию не слыхали?
По уму, там интерфейс нужен типа такого
interface Subscriber<T> {
    void accept(T const &arg);
}


Тё>>Чувачелло, величина твоего невежества зашкаливает. Но я же привёл ссылку. Сложно прочитать?

Тё>>

Тё>>>>https://en.wikipedia.org/wiki/Sentinel_node#Linked_list_implementation


S>Т.е. вы для хранения списка подписок предлагаете хранить еще и специальный sentinel node?

Я не "предлагаю" — это оптимизация связного списка для упрощения его операций, почитайте, учиться ведь всегда полезно.

Тё>>Если пописчиков немного, то не стоит заморачиваться на алгоритмическую сложность.


S>Если вы еще не заметили, то речь идет не про алгоритмическую сложность, а о стоимости по памяти и времени исполнения. В случаях, когда подписчиков немного.


Тё>>Кто управляет временем жизни callback?


S>Подписчик.

Ну вот ваш подписчик должен хранить интерфейс для отписки. Может хранить пачку таких подписок в списке, и отписываться в деструкторе, например. Тоже такой наивный способ. Элегантный способ в http://reactivex.io/ — использовать оператор takeUntil().

S>>>Если достаточно всего лишь указателя на callback, то хранение для каждой подписки Subscription -- это дополнительная головная боль. Особенно в C++, где ничего не защищает от обращения к повисшим указателям.

Тё>>У хорошего плюсника не бывает тухлых указателей. Вы к таким определённо не относитесь.

S>Без разницы к каким вы меня относите. Суть в том, что такая проблема есть. И решений, которые ее провоцируют, следует избегать. Тогда будет не важно, хороший плюсник работает с кодом или нет.


S>>> Использовали экземпляр subscription для отписки один раз, а потом, по ошибке, сделали отписку повторно. И что будет в итоге?

Тё>>В итоге будет nullptr и это правильно. Ибо кривые руки повторно-вызывальщиков отписок, релизов, диспозов и прочих делетов нужно испрямнять жёстко и без церемоний.

S>На словах все герои. Только вот если у вас отписка работает через поиск (по указателю на callback или по какому-то уникальному Id), то она оказывается более устойчивой к подобным ошибкам.

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

S>Кроме того, в C++ объекты по умолчанию копируются. Т.е. если есть:

S>
S>class Subscription {
S>  Node * node_;
S>public:
S>  ...
S>  void unsubscribe() {
S>    if(node_) {
S>      ...
S>      node_ = nullptr;
S>    }
S>  }
S>};
S>

S>То потребуется еще позаботится о том, чтобы объекты Subscription не копировались. Потому что зануление node_ в копии никак не скажется на исходном объекте. А до C++11 нормальных средств для этого в языке не было (а код от B0FEE664 явно написан для C++98).
Возвращается ссылка на интерфейс Subscription. Это может быть наследник от Node имплементирующий Subscription. О каком каком копировании вы поёте?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.