Re[7]: Unified Pointer Library
От: so5team https://stiffstream.com
Дата: 18.06.18 10:24
Оценка:
Здравствуйте, ViTech, Вы писали:

S>>Допустим, что это не так, что вы действительно сделали полезную штуку. Объясните, пожалуйста, в каких условиях она кому-нибудь вообще может потребоваться. Пока во всей теме вменяемых объяснений еще не было.


VT>Эта штука, в первую очередь, нужна мне. Мне она нужна в условиях работы в многопоточной среде для организации ассоциативных связей между объектами. В частности, для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей. Если взять пример TransferUnique, то я хочу, чтобы Car уникально владел Engine. И чтобы можно было передать владение Engine или из фабрики, или сняв с другого Car, через очередь сообщений/команд. std::unique_ptr в std::function<void()> не лезет. Можно сырые указатели пересылать, но мне это не нравится.


Скажите, а вы нормальным языком постановку задачи сделать можете?

А то фразы вроде "для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей" не понятны от слова совсем.

Ну и "std::unique_ptr в std::function<void()> не лезет" так же не мешало бы расшифровать. Вы ограничены рамками C++11?
Re[8]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 10:55
Оценка:
Здравствуйте, so5team, Вы писали:

S>Скажите, а вы нормальным языком постановку задачи сделать можете?

S>А то фразы вроде "для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей" не понятны от слова совсем.
S>Ну и "std::unique_ptr в std::function<void()> не лезет" так же не мешало бы расшифровать. Вы ограничены рамками C++11?

Т.е. что происходит в этом примере, в частности здесь, вам не понятно? Хорошо, вот более короткий вариант:
#include <memory>
#include <functional>
#include <iostream>

using namespace std;

void foo(shared_ptr<int> ptr) { cout << "foo shared: " << *ptr << endl; }
void bar(unique_ptr<int> ptr) { cout << "bar unique: " << *ptr << endl; }

int main()
{
    auto s = make_shared<int>(7);
    function<void()> foo_f = bind(&foo, move(s));
    foo_f();

    auto u = make_unique<int>(7);
    function<void()> bar_f = bind(&bar, move(u)); // error: conversion from 'std::_Bind_helper<false, void (*)(std::unique_ptr<int>)...
    bar_f();

    return 0;
}
Пока сам не сделаешь...
Re[4]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 11:06
Оценка:
Здравствуйте, vopl, Вы писали:

V>С такого — противоречий нет. Оригинальный вопрос был не про противоположный полюс.

V>
V>class Car;
V>class Engine;

V>class Car
V>{
V>    upl::unique<Engine> engineStrong;   //рассматриваем этот unique как полюс ассоциации "машина [0,1] -- [0,1] двигатель"
V>    upl::weak<Engine>   engineWeak;     //альтернативный полюс для engineStrong. Вот про него речь. С ним проблемы.
V>};

V>class Engine
V>{
V>    unspecified<Car> car;               //противоположный для engineStrong+engineWeak, может быть upl::weak, а может что то другое. Не интересует
V>};
V>


Допустим, есть класс, который наблюдает за двигателем:
class Monitor
{
    upl::weak<Engine> engineWeak;
}


Если двигатель внезапно удалится, то монитор должен корректно обрабатывать такую ситуацию. Если в Car будет использоваться std::unique_ptr<Engine>, то как предлагаете Monitor писать?
Пока сам не сделаешь...
Re[9]: Unified Pointer Library
От: so5team https://stiffstream.com
Дата: 18.06.18 11:26
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Т.е. что происходит в этом примере


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

И что именно вы подразумеваете, когда говорите: "для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей"

VT>Хорошо, вот более короткий вариант:


Теперь ясно о чем вы.
Re[10]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 11:34
Оценка:
Здравствуйте, so5team, Вы писали:

S>И что именно вы подразумеваете, когда говорите: "для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей"


Чуть выше пример с Car, Engine и Monitor. Например, я хочу, чтобы Car уникально владел Engine, а Monitor мог наблюдать за Engine. Как предлагаете это делать стандартными указателями С++ в многопоточной среде, чтобы избежать проблемы с dangling pointers? Или это странное желание и так делать не надо?
Пока сам не сделаешь...
Re[11]: Unified Pointer Library
От: so5team https://stiffstream.com
Дата: 18.06.18 11:39
Оценка:
Здравствуйте, ViTech, Вы писали:

S>>И что именно вы подразумеваете, когда говорите: "для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей"


VT>Чуть выше пример с Car, Engine и Monitor. Например, я хочу, чтобы Car уникально владел Engine, а Monitor мог наблюдать за Engine. Как предлагаете это делать стандартными указателями С++ в многопоточной среде, чтобы избежать проблемы с dangling pointers? Или это странное желание и так делать не надо?


Самый простой способ -- это использовать std::shared_ptr. Потому, что реально у вас совместное владение объектом Engine (и в Car, и в Monitor). Поскольку Engine не может быть уничтожен раньше, чем умрут оба -- и Car и Monitor.

Более сложный -- обеспечивать контроль времени жизни Car каким-то другими средствами. Например, явно в своей программе уничтожать сперва Monitor, затем Car.
Re[5]: Unified Pointer Library
От: vopl Россия  
Дата: 18.06.18 11:52
Оценка:
Здравствуйте, ViTech, Вы писали:

Понятно. Ты натянул устоявшуюся терминологию из одной области на другую область, это сильно сбивает с толку. Смени названия на что нибудь более близкое именно к UML-ассоциации с сотоварищами, станет намного лучше и органичнее.
Re[12]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 11:59
Оценка:
Здравствуйте, so5team, Вы писали:

S>Самый простой способ -- это использовать std::shared_ptr. Потому, что реально у вас совместное владение объектом Engine (и в Car, и в Monitor). Поскольку Engine не может быть уничтожен раньше, чем умрут оба -- и Car и Monitor.


Реально у меня Monitor не владеет Engine ни в коде (upl::weak), ни в модели UML. Если помрёт Engine, то Monitor это нормально переживёт. Он не владеет Engine, лишь продлевает время его жизни на момент работы с ним, если обратился к ещё существующему объекту. А если объект уже удалился, то и при обращении к нему об этом будет известно. Можно всё через std::shared_ptr делать, если не нужно соблюдать уникальные связи. Ну и модели UML это не будет соответствовать, если в ней композитная агрегация прописана.

S>Более сложный -- обеспечивать контроль времени жизни Car каким-то другими средствами. Например, явно в своей программе уничтожать сперва Monitor, затем Car.


Хорошо бы так. Но не факт, что обеспечивать контроль жизни объектов другими средствами проще, чем изобрести weak для unique.
Пока сам не сделаешь...
Re[13]: Unified Pointer Library
От: so5team https://stiffstream.com
Дата: 18.06.18 12:07
Оценка:
Здравствуйте, ViTech, Вы писали:

S>>Самый простой способ -- это использовать std::shared_ptr. Потому, что реально у вас совместное владение объектом Engine (и в Car, и в Monitor). Поскольку Engine не может быть уничтожен раньше, чем умрут оба -- и Car и Monitor.


VT>Реально у меня Monitor не владеет Engine ни в коде (upl::weak), ни в модели UML.


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

VT>Если помрёт Engine, то Monitor это нормально переживёт.


Фокус в том, что у вас и Car, и Monitor владеют Engine, вы только не находите сил себе в этом признаться. Представьте ситуацию, что на одном рабочем потоке Monitor проапгрейдил ссылку на Engine с weak на strong. А после этого на другом рабочем потоке будет уничтожен Car.

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

И вместо того, чтобы назвать вещи своими именами вы делаете собственный велосипед, который повторяет функциональность shared_ptr, но запутывает программиста псевдо-концепциями upl::unique и upl::universal (или как они там у вас называются).
Re[3]: Unified Pointer Library
От: kov_serg Россия  
Дата: 18.06.18 12:11
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>Здравствуйте, kov_serg, Вы писали:


_>>Ждём Unified Math Library, Unified GUI Libaray и Unified Coroutine and Threading Library.


XOO>А так же Unified Qt Library, Unified STL Library и Unified Boost Library.


Слона надо есть по частям
Re[6]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 12:27
Оценка:
Здравствуйте, vopl, Вы писали:

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


Соприкосновение областей описано в разделе Владение. Допустим, вместо upl::unique будет название upl::composite, какое название предложите для указателя, который выражает AggregationKind::none? Подозреваю, что на вопросы: "Что это за upl::composite такой?", пришлось бы отвечать: "Ну это как std::unique_ptr". И в общем не всё так просто, как может показаться на первый взгляд.

В библиотеке UPL терминология указателей используется специально, чтобы не грузить концепциями UML и было привычнее переходить/использовать совместно с умными указателями C++. Нужно только уточнить, что эти указатели выражают семантику ассоциативных связей. И могут быть, грубо говоря, как std::optional и gsl::not_null. UPL — это облегчённый набор, с минимумом зависимостей и без дебрей UML. Для дебрей UML есть отдельный проект: CppUml.
Пока сам не сделаешь...
Re[14]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 12:51
Оценка:
Здравствуйте, so5team, Вы писали:

S>У вас каша в голове. Происходит это потому, что вы не можете смириться с тем, что существует разрыв между UML-моделями и особенностями их воплощения в коде на конкретном языке.


Я смотрю, вы очень хорошо знаете, что у других в головах происходит .

S>Фокус в том, что у вас и Car, и Monitor владеют Engine, вы только не находите сил себе в этом признаться. Представьте ситуацию, что на одном рабочем потоке Monitor проапгрейдил ссылку на Engine с weak на strong. А после этого на другом рабочем потоке будет уничтожен Car.


S>Ведь у вас Engine останется жив до тех пор, пока в Monitor не умрет string-ссылка на Engine. А это есть ни что иное, как влияние на время жизни, т.е. то самое совместное владение, наличие которого вы никак не можете признать.


Фокус в том, что именно такое поведение мне и нужно. Чтобы во время работы с Engine в Monitor не было вылета посреди работы метода. Как вариант, можно блокировать поток, который хочет удалить объект, пока с ним работают другие потоки. Не уверен, что этот вариант лучше. Можно попытаться, перед удалением Engine в Car удалить все weak-ссылки на него, но это тоже может быть непросто. При этом, я хочу отделять уникальное владение Engine в Car от совместного. Да, я хочу писать программы в соответствии с моделями UML.

S>И вместо того, чтобы назвать вещи своими именами вы делаете собственный велосипед, который повторяет функциональность shared_ptr, но запутывает программиста псевдо-концепциями upl::unique и upl::universal (или как они там у вас называются).


Если вам хватает функциональности std::shared_ptr, и не нужны всякие псевдоконцепции, то и ладно . И будем считать, что вы меня разоблачили, и других программистов предупредили о ереси в UPL.
Пока сам не сделаешь...
Re[15]: Unified Pointer Library
От: so5team https://stiffstream.com
Дата: 18.06.18 13:05
Оценка:
Здравствуйте, ViTech, Вы писали:

S>>Ведь у вас Engine останется жив до тех пор, пока в Monitor не умрет string-ссылка на Engine. А это есть ни что иное, как влияние на время жизни, т.е. то самое совместное владение, наличие которого вы никак не можете признать.


VT>Фокус в том, что именно такое поведение мне и нужно.


Фокус в том, что именно такое поведение вам и дает shared_ptr. И нет надобности в изобретении его аналогов с вводящими в заблуждение именами.

Если вы так уж хотите иметь именно "владеющий указатель", а не голый shared_ptr, то нет ничего сложного в создании обертки:
class UniqueEngine {
  std::shared_ptr<Engine> engine_;
public:
  UniqueEngine(const UniqueEngine &) = disable;
  UniqueEngine(UniqueEngine &&) = default;
  UniqueEngine(std::unique_ptr<Engine> en) : engine_(std::move(en)) {}
  ...
  std::weak_ptr<Engine> weak_ref() { return {engine_}; }
  ...
};
...
class Car {
  UniqueEngine engine_;
  ...
public:
  auto engine() { return engine_.weak_ref(); }
};
class Monitor {
  std::weak_ptr<Engine> engine_;
  ...
};

Но и это уже оверинжениринг какой-то.

Может вам вообще нужно просто что-то вроде:
class Car : public std::enable_shared_from_this {
  Engine engine_;
public:
  std::weak_ptr<Engine> engine() {
    return { std::shared_ptr<Engine>(shared_from_this(), &engine) };
  };
};


VT>Да, я хочу писать программы в соответствии с моделями UML.


Пишите. Только сперва разберитесь каким естественным образом понятия из UML ложатся на C++, а не придумывайте велосипеды.

VT>Если вам хватает функциональности std::shared_ptr, и не нужны всякие псевдоконцепции, то и ладно


Не видно объективных причин для того, чтобы придумывать еще что-то сверх того. И вы не можете привести убедительных доводов.
Re[7]: Unified Pointer Library
От: vopl Россия  
Дата: 18.06.18 15:21
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Здравствуйте, vopl, Вы писали:


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


VT>Соприкосновение областей описано в разделе Владение. Допустим, вместо upl::unique будет название upl::composite, какое название предложите для указателя, который выражает AggregationKind::none? Подозреваю, что на вопросы: "Что это за upl::composite такой?", пришлось бы отвечать: "Ну это как std::unique_ptr".


Да даже если оно будет называться composite (хотя наверное можно и получше имя найти) — уверен, человеку легче заранее почитать спецификацию на этот composite и сразу начать его правильно думать, чем увидев обще-употребительное наименование типа unique pointer начать его использовать с интуитивными ожиданиями а потом обнаружить что это совсем не то.
Re[8]: Unified Pointer Library
От: ViTech  
Дата: 18.06.18 16:01
Оценка:
Здравствуйте, vopl, Вы писали:

V>Да даже если оно будет называться composite (хотя наверное можно и получше имя найти) — уверен, человеку легче заранее почитать спецификацию на этот composite и сразу начать его правильно думать, чем увидев обще-употребительное наименование типа unique pointer начать его использовать с интуитивными ожиданиями а потом обнаружить что это совсем не то.


Можно много всего получше сделать, поэтому хотелось бы услышать предложения по наименованиям. И что смущает в поведении upl::unique? Что объект под его управлением удаляется не сразу, а чуть погодя, когда с ним закончат работать методы объектов, которые имеют слабую ссылку на него? Он и сразу может удалиться, если с ним в текущий момент никто не работает.
Пока сам не сделаешь...
Re[9]: Unified Pointer Library
От: _NN_ www.nemerleweb.com
Дата: 19.06.18 07:58
Оценка:
Здравствуйте, ViTech, Вы писали:


Зачем bind если можно простой лямбдой ?
bind предполагает копирование, которого нет.
Что будете делать с другими некопируемыми классами ? Создавать копируемые аналоги как ваш unique ?

function<void()> foo_f = [&]{foo(move(s));};
function<void()> bar_f = [&]{bar(move(u));};
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[10]: Unified Pointer Library
От: ViTech  
Дата: 19.06.18 08:43
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Зачем bind если можно простой лямбдой ?

_NN>bind предполагает копирование, которого нет.

std::bind как раз копирование не предполагает, можно сделать auto some = bind(...); с перемещением в него std::unique_ptr. Но вот дальше эту some в std::function<void()> поместить не получится, именно там требуется копирование.

_NN>
_NN>function<void()> foo_f = [&]{foo(move(s));};
_NN>function<void()> bar_f = [&]{bar(move(u));};
_NN>


Что произойдёт, когда указатель выйдет из области видимости?

#include <memory>
#include <functional>
#include <vector>
#include <iostream>

using namespace std;

void bar(unique_ptr<int> ptr) { cout << "bar unique: " << *ptr << endl; }

int main()
{
    vector<function<void()>> commands;
    {
        auto u = make_unique<int>(7);
        commands.push_back([&] { bar(move(u)); });
    }
    commands[0]();

    return 0;
}


_NN>Что будете делать с другими некопируемыми классами ? Создавать копируемые аналоги как ваш unique ?


Ничего не буду делать . Умные указатели же работают с некопируемыми классами. Копируются указатели, а не сам объект.
Пока сам не сделаешь...
Re[9]: Unified Pointer Library
От: vopl Россия  
Дата: 19.06.18 09:13
Оценка: +1
Здравствуйте, ViTech, Вы писали:

V>>Да даже если оно будет называться composite (хотя наверное можно и получше имя найти) — уверен, человеку легче заранее почитать спецификацию на этот composite и сразу начать его правильно думать, чем увидев обще-употребительное наименование типа unique pointer начать его использовать с интуитивными ожиданиями а потом обнаружить что это совсем не то.


VT>Можно много всего получше сделать, поэтому хотелось бы услышать предложения по наименованиям.


К сожалению, не проникся принципами upl до глубины, поэтому вряд ли смогу генерировать эффективные наименования

VT>И что смущает в поведении upl::unique? Что объект под его управлением удаляется не сразу, а чуть погодя, когда с ним закончат работать методы объектов, которые имеют слабую ссылку на него? Он и сразу может удалиться, если с ним в текущий момент никто не работает.


Ну, тут сплошные засады Ты просто накладываешь полезняшки на чашу весов какого то своего скрытого кейса. Но надо понимать, что если ты на свою чашу что то добавил — то с другой забрал. Например, ты убил детерминированность времени жизни указываемого объекта, а существует большое число прикладных кейсов, в которых такая детерминированность нужна/полезна. Например, ты существенно увеличил расход ресурсов потому что для твоего кейса это не существенно, но для многих перерасход будет фатальным. Клоню к тому, что "унификации" не получилось. Получился какой то сугубо конкретный тул. Да еще и чужую терминологию употребил, чем сбил всех с толку, а с so5team даже подрался
Re[7]: Unified Pointer Library
От: Maniacal Россия  
Дата: 19.06.18 10:12
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Эта штука, в первую очередь, нужна мне. Мне она нужна в условиях работы в многопоточной среде для организации ассоциативных связей между объектами. В частности, для нормальной поддержки уникального владения (композитной агрегации), чтобы соблюдалась целостность связей.


Это жесть, конечно. Я всегда думал, что в UML есть три типа связей: агрегация, композиция и ассоциация (общий случай агрегации и композиции).
Re[10]: Unified Pointer Library
От: ViTech  
Дата: 19.06.18 10:19
Оценка:
Здравствуйте, vopl, Вы писали:

V>Ну, тут сплошные засады Ты просто накладываешь полезняшки на чашу весов какого то своего скрытого кейса. Но надо понимать, что если ты на свою чашу что то добавил — то с другой забрал. Например, ты убил детерминированность времени жизни указываемого объекта, а существует большое число прикладных кейсов, в которых такая детерминированность нужна/полезна. Например, ты существенно увеличил расход ресурсов потому что для твоего кейса это не существенно, но для многих перерасход будет фатальным. Клоню к тому, что "унификации" не получилось. Получился какой то сугубо конкретный тул. Да еще и чужую терминологию употребил, чем сбил всех с толку, а с so5team даже подрался


Я во Введении вроде основные особенности расписал. И не говорил: "Бросайте ущербные указатели C++ и переходите на самые лучшие в мире унифицированные указатели! Без СМС и регистрации!" . Наоборот, отдельно отметил:

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


Кейс тоже вроде не особо скрытый:

Указатель upl::weak может ссылаться на объект, который находится под управлением upl::unique

Кто работал со связкой std::weak_ptr <-> std::shared_ptr, по-моему, должен понять, о чём речь идёт.

По поводу детерминированности времени жизни указываемого объекта. Да, обычное поведение std::unique_ptr — это удалять объект, когда уничтожается сам указатель. И если требуется именно такое поведение, значит нужно использовать std::unique_ptr и не использовать upl::unique. Но разве в стандарте С++ говорится только о таком единственном поведении std::unique_ptr? Что объект однозначно должен быть уничтожен сразу и в том же потоке. Стандарт С++ сложно читать, и я мог пропустить такое описание, пожалуйста, покажите, если там такое есть. Я вижу, что речь там идёт о deleter, который "a function object whose correct invocation results in p’s appropriate disposition (typically its deletion).". Обязан deleter немедленно и в том же потоке удалять объект? Можно ли создать std::unique_ptr с deleter, который отложенно удалит объект, когда будет уверен, что с этим объектом никто не работает? Думаю, можно считать, что upl::unique имеет такое же поведение, как std::unique_ptr с отложенным deleter.

Накладные расходы, естественно есть, за всё надо платить. Но если вместо upl::unique использовать std::shared_ptr, чтобы получить "похожую" функциональность, то перерасход ресурсов не такой уж и большой, и зависит от реализации.
Пока сам не сделаешь...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.