Re[10]: c#
От: noone  
Дата: 06.05.13 12:06
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Попробуй соорудить реализацию объекта с Dispose в которой бы:

КД>- было запрещено использовать объект после вызова Dispose.
КД>- Dispose не "разрушал" объект, пока работают другие его методы.

Нужен, как я понял, shared ресурс: счетчик ссылок в руки, он как раз для этого придуман. Файлы и сокеты не грозят циклическими ссылками (кроме каких-нибудь патологических случаев), так что механизм отлично будет работать.
Кстати, Microsoft мог встроить автоматическую поддержку этого для IDisposable в компилятор/рантайм, раз уж они начали. Видимо, есть занятия поважней.
Re[13]: c#
От: MTD https://github.com/mtrempoltsev
Дата: 06.05.13 12:11
Оценка:
Здравствуйте, noone, Вы писали:

N>Этот бред имеет отдельную поддержку от языка в C# — http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx . Наверное, от скуки они его туда 10 лет назад приделали, тебя потроллить.


Нет, тролишь здесь похоже ты. Или ты приведешь адекватный пример?
Re[11]: c#
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.05.13 12:27
Оценка:
Здравствуйте, noone, Вы писали:

КД>>Попробуй соорудить реализацию объекта с Dispose в которой бы:

КД>>- было запрещено использовать объект после вызова Dispose.
КД>>- Dispose не "разрушал" объект, пока работают другие его методы.

N>Нужен, как я понял, shared ресурс: счетчик ссылок в руки, он как раз для этого придуман. Файлы и сокеты не грозят циклическими ссылками (кроме каких-нибудь патологических случаев), так что механизм отлично будет работать.

N>Кстати, Microsoft мог встроить автоматическую поддержку этого для IDisposable в компилятор/рантайм, раз уж они начали. Видимо, есть занятия поважней.

Не, это только начало.

Допустим, правильную реализацию Dispose мы победили.

А теперь следующая задача.

Есть два связанных объекта. Пусть это будет подключение и транзакция. И нужно запретить диспозить подключение, пока работает код в объекте транзакции.

Опять юзаем счетчик ссылок. Только счетчик находится в одном объекте, а инкрементит/декрементит его другой объект.

И еще нужно не забыть прикрутить ко всему этому делу CER, чтобы гарантированно выполнить декремент. Я прав?

Вообщем, лично у меня сформировалось мнение — что счетчик ссылок это костыли не для плюсов (где, формально, это фундамент для более менее сложных вещей, и его не замечают так же как воздух), а для C#-а

---
Но мне нравится писать на обоих языках

-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[6]: c#
От: Евгений Акиньшин grapholite.com
Дата: 06.05.13 12:41
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>Здравствуйте, Евгений Акиньшин, Вы писали:


MTD>>> но замечу, что циклические ссылки — проблема кривого дизайна


ЕА>>Это когда они стали плохим дизайном и почему


MTD>Уточнение — владеющие. Это из контекста понятно.


Ну может кому-то и понятно, а в управляемых средах нет необходимости в искусственных разграничениях на владеющие\ не владеющие ссылки
Не шалю, никого не трогаю, починяю примус Diagrams Designer for iPad and Windows 10
Re[12]: c#
От: Sinix  
Дата: 06.05.13 12:53
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, Sinix, Вы писали:


КД>>>Попробуй соорудить реализацию объекта с Dispose в которой бы:

КД>>>- было запрещено использовать объект после вызова Dispose.
КД>>>- Dispose не "разрушал" объект, пока работают другие его методы.

S>>Дотнетовский Dispose заточен под самый популярный сценарий — один владелец, объект гарантированно не будет использоваться в дальнейшем.


КД>Кем гарантируется? Программистом?!


Языком (см using). При нормальном процессе разработки ещё и FxCop-ом на билдсервере

dispose + using заточен под сценарии, когда время жизни ресурса заведомо меньше цикла сборки мусора, иначе освобождение ресурсов (если оно вообще требуется) спокойно может переехать в финалайзер.

как наглядный пример:
using (var fileWriter = OpenFile(...))
{
  // запись в файл
  // ...
} // Происходит вызов fileWriter.Dispose()
// здесь к fileWriter-у при всём желании не обратишься.


Если настроен FxCop и забыли обернуть xmlWriter в using — будет предупреждение (или ошибка, смотря как настроить) при сборке.

Если ваш ресурс должен жить столько же, сколько овнер, то овнер тоже должен реализовать IDisposable и освобождать используемые ресурсы. Забыли — снова варнинг.

КД>Упаси меня Господь закладываться на такие гарантии

Эмм... какие ещё гарантии нужны?

>> Я бы смотрел в сторону RX/тасков.

КД>Не, спасибо (хоть бы ссылку дали, что-ли, для темных).

Rx:
http://msdn.microsoft.com/en-us/data/gg577611.aspx
http://www.introtorx.com/

Таски:
http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx
http://blogs.msdn.com/b/pfxteam/

Но перед тем, как туда лезть, придётся основательно подучить матчасть и определиться с задачей, иначе выйдет только хуже.

Если проблема вот в этом:

Есть два связанных объекта. Пусть это будет подключение и транзакция. И нужно запретить диспозить подключение, пока работает код в объекте транзакции.

то использование dispose напрямую вам ничем не поможет. Если отвлечься от самой проблемы:
— транзакция подписывается на connection.Closing и кидает исключение, если что не так.
— соединение хранит внутри себя аналог RefCountDisposable из Rx и отдаёт транзакции ссылку через GetDisposable()

Если не отвлекаться — нужно подробно изучать вот этот док. Ресурсы в транзакции (особенно в распределённых транзакциях) — достаточно сложная штука, свои велосипеды вылезут боком.
Re[12]: c#
От: noone  
Дата: 06.05.13 13:48
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, noone, Вы писали:


КД>Есть два связанных объекта. Пусть это будет подключение и транзакция. И нужно запретить диспозить подключение, пока работает код в объекте транзакции.

КД>Опять юзаем счетчик ссылок. Только счетчик находится в одном объекте, а инкрементит/декрементит его другой объект.
КД>И еще нужно не забыть прикрутить ко всему этому делу CER, чтобы гарантированно выполнить декремент. Я прав?

Аббревиатуру не осилил, но идея понятна. Да, все как ты сказал.

КД>Вообщем, лично у меня сформировалось мнение — что счетчик ссылок это костыли не для плюсов (где, формально, это фундамент для более менее сложных вещей, и его не замечают так же как воздух), а для C#-а


Сам механизм подсчета ссылок не хороший и не плохой, он просто есть и имеет некоторую семантику. В C++ он реализован через костыль — семейство *_ptr и используется везде, в C# — тоже (классы с ручным retain/release) и используется только для внешних к программе ресурсов. Пример подсчета без костылей — современный Objective-C, где сохраняются все достоинства подсчета и его недостатки, но, по крайней мере, он поддерживается непосредственно компилятором. Это очень важное свойство — доступна куча статических проверок и взаимодействие между библиотеками от разных автором в области управления памятью прозрачное насколько это возможно.

КД>---

КД>Но мне нравится писать на обоих языках

Это не возбраняется .
Re[13]: c#
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.05.13 14:53
Оценка:
Здравствуйте, noone, Вы писали:

КД>>Есть два связанных объекта. Пусть это будет подключение и транзакция. И нужно запретить диспозить подключение, пока работает код в объекте транзакции.

КД>>Опять юзаем счетчик ссылок. Только счетчик находится в одном объекте, а инкрементит/декрементит его другой объект.
КД>>И еще нужно не забыть прикрутить ко всему этому делу CER, чтобы гарантированно выполнить декремент. Я прав?

N>Аббревиатуру не осилил, но идея понятна. Да, все как ты сказал.


Это я про "Constrained Execution Regions" говорил.

N>Сам механизм подсчета ссылок не хороший и не плохой, он просто есть и имеет некоторую семантику. В C++ он реализован через костыль — семейство *_ptr


Я всегда думал, что "костыль" (в плане счетчика ссылок) это когда руками вызываешь AddRef/Release и постоянно паришься чтобы не облажаться с ними. В нормально спроектированной программе таких проблем нет.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[14]: c#
От: noone  
Дата: 06.05.13 15:13
Оценка: :)
Здравствуйте, MTD, Вы писали:

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


N>>Этот бред имеет отдельную поддержку от языка в C# — http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx . Наверное, от скуки они его туда 10 лет назад приделали, тебя потроллить.


MTD>Нет, тролишь здесь похоже ты. Или ты приведешь адекватный пример?


Это натурально простейший практический кусочек, проще него только репа. Примеров на C# можно обчитаться в вышеприведенной ссылке. Вот микропример на Java

public class MyPanel extends JPanel {
    JButton myButton;

    private void initButton() {
        myButton = new JButton("Do something");
        myButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doSomething();
            }
        });
        add(myButton);
    }

    private void doSomething() {
    }
}


При подсчете ссылок придется явно городить слабую ссылку на this (костыль). В чуть более сложном случае — курить бамбук (много костылей) с риском получить висячие ссылки/утечки.
Re[14]: c#
От: noone  
Дата: 06.05.13 15:27
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, noone, Вы писали:


КД>Это я про "Constrained Execution Regions" говорил.


Это вовсе необязательно. Декремент делается в finally.

N>>Сам механизм подсчета ссылок не хороший и не плохой, он просто есть и имеет некоторую семантику. В C++ он реализован через костыль — семейство *_ptr


КД>Я всегда думал, что "костыль" (в плане счетчика ссылок) это когда руками вызываешь AddRef/Release и постоянно паришься чтобы не облажаться с ними.


Да. А еще костыль это еще когда тулзы не могут при взгляде на программу сказать, что же тут происходит. Или когда в дебаггере черт ногу сломит из-за лишних объектов. Когда умных указателей целый зоопарк, и в каждой библиотеке он свой, и есть тонна имплицитных преобразований между одними и другими (пользуясь случаем, передаю привет WebKit вообще и PassRefPtr в частности). Одним словом, костыль это когда семантика языка плохо ложится на задачу и средствами языка правится плохо.
Re[15]: c#
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.05.13 15:55
Оценка:
Здравствуйте, noone, Вы писали:

КД>>Это я про "Constrained Execution Regions" говорил.


N>Это вовсе необязательно. Декремент делается в finally.


Ага. Он у меня и делается в finally. Надо только что бы этот finally гарантировано вызвался. Для этого и юзаю CER. Может я что конечно попутал в этом деле, но решил перестраховаться по-полной

Впрочем, я сверялся с кодом из самого фреймворка, и думаю я ничего не напутал.

N>Да. А еще костыль это еще когда тулзы не могут при взгляде на программу сказать, что же тут происходит. Или когда в дебаггере черт ногу сломит из-за лишних объектов. Когда умных указателей целый зоопарк, и в каждой библиотеке он свой, и есть тонна имплицитных преобразований между одними и другими (пользуясь случаем, передаю привет WebKit вообще и PassRefPtr в частности). Одним словом, костыль это когда семантика языка плохо ложится на задачу и средствами языка правится плохо.


Не, ну зоопарк можно где угодно соорудить

У меня только два типа смарт-указателей — для COM-а и для моих классов. И они никак не пересекаются. Можно считать — полная гармония и умиротворенность

А от всяких ужосов типа буста и еже с ними — я (по правде говоря) шарахаюсь

Со сложностью борюсь всякими злобными методами. Перечислять которые нет смысла.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: c#
От: Константин Черногория  
Дата: 06.05.13 18:23
Оценка: :)
Здравствуйте, Kubyshev Andrey, Вы писали:

KA>Лет 10 ездил на коробке. Думал нафига мне автомат, коробка это же "все под контролем". Пересел на автомат, на коробку обратно не хочу

По годным дорогам без снега и пробок — разница минимальна между ними.

KA>СиПлюсПлюсил много лет, попробовал по-СиШарпить — обратно не хочется.

Странно, переходил пару раз в обе стороны, особых неудобств не замечал.

Как вам верно заметили выше, при наличии некоторого опыта за плечами и умением пользоваться STL или лучше ATL, управление памятью в С++ практически перестаёт создавать проблем.
Алгоритмы с графами реализуются элементарно, как только поймёте шо это не ноды владеют друг другом, а граф владеет всеми нодами, которые конечно ссылаются друг на друга, но не владеют.
В качестве бесплатного бонуса, вы получите ускорение алгоритма на десятки процентов, потому шо становится технически просто разместить все ноды графа в последовательных адресах памяти.

Из языков на которых программирую, сложнее всего с управлением памятью в Оbjective-C — у Apple как обычно всё через задницу.
Re[7]: c#
От: Jack128  
Дата: 06.05.13 18:47
Оценка:
Здравствуйте, Евгений Акиньшин, Вы писали:

ЕА>Ну может кому-то и понятно, а в управляемых средах нет необходимости в искусственных разграничениях на владеющие\ не владеющие ссылки


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

http://ideone.com/p5tL8Z
Re[13]: c#
От: Ночной Смотрящий Россия  
Дата: 06.05.13 18:50
Оценка:
Здравствуйте, noone, Вы писали:

N>Этот бред имеет отдельную поддержку от языка в C# — http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx


Смешались в кучу кони, люди ... Встроенная в платформу реализация publisher/subscriber это event. Delegate это просто функциональный тип. И да, можно обходится и без event, как в других языках, Rx тому примером.
Re[14]: c#
От: Константин Черногория  
Дата: 06.05.13 18:55
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Встроенная в платформу реализация publisher/subscriber это event.

Да, это один из самых популярных методов, которые мне попадались, "как сделать утечку памяти на C#".
Re[15]: c#
От: MTD https://github.com/mtrempoltsev
Дата: 06.05.13 18:56
Оценка:
Здравствуйте, noone, Вы писали:

N>Это натурально простейший практический кусочек, проще него только репа. Примеров на C# можно обчитаться в вышеприведенной ссылке. Вот микропример на Java


N>При подсчете ссылок придется явно городить слабую ссылку на this (костыль). В чуть более сложном случае — курить бамбук (много костылей) с риском получить висячие ссылки/утечки.


Вот, наконец адекватный пример. Так вот, если из плюсов пытаться яву сделать, то да, будет связка shared_ptr/weak_ptr. А если на плюсах писать, то будет так:

class Button
{
    typedef boost::signal0<void> Signal;
    typedef Signal::slot_type Slot;

    Signal onClick_;

    void addOnClickHandler(Slot handler)
    {
        onClick_.connect(handler);
    }
};

class Panel
{
    const boost::scoped_ptr<Button> button_;

    Panel()
        : button_(new Button())
    {
        button_->addOnClickHandler(boost::bind(&Panel::onClick, this));
    }
};
Re[14]: c#
От: noone  
Дата: 06.05.13 19:26
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Смешались в кучу кони, люди ... Встроенная в платформу реализация publisher/subscriber это event. Delegate это просто функциональный тип. И да, можно обходится и без event, как в других языках, Rx тому примером.


OK. Назовем все это Observer — лучше?
То, что можно обойтись без чего угодно, я знаю. Вернемся к исходному вопросу: могу ли я сохранить объект, который мне пришел в метод/функцию, или нет? И что делать, когда объект точно нужен, но сохранять его нельзя, т.к. есть вероятность цикла? Правильно: перепиливаем архитектуру, добавляем хаки по вкусу. Или используем GC.
Re[16]: c#
От: noone  
Дата: 06.05.13 19:29
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>Вот, наконец адекватный пример. Так вот, если из плюсов пытаться яву сделать, то да, будет связка shared_ptr/weak_ptr. А если на плюсах писать, то будет так:


Это тот же самый пример (чуть проще). Интересно, что ты его узнал только когда речь пошла о UI.

MTD>
MTD>        button_-> addOnClickHandler(boost::bind(&Panel::onClick, this));
MTD>


Здесь мы наблюдаем, как байндится raw-указатель this, то есть явно используется факт того, что кнопка живет не дольше this. Чуть усложним Java-пример:

interface Listener {
    void doSomething();
}

public class MyPanel extends JPanel implements Listener {
    JButton myButton;

    public void initButton(final Listener listener) {
        myButton = new JButton("Do something");
        myButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                listener.doSomething();
            }
        });
        add(myButton);
    }

    @Override
    public void doSomething() {
    }

    public static void main(String[] args) {
        MyPanel p = new MyPanel();

        p.initButton(p);

        p.initButton(new Listener() {
            @Override
            public void doSomething() {
            }
        });
    }
}


Теперь в initButton может передаваться как this, так и совершенно посторонний listener. Время жизни зарегистрированного listener должно быть не меньше времени жизни кнопки.
Re[2]: c#
От: noone  
Дата: 06.05.13 19:33
Оценка:
Здравствуйте, Константин, Вы писали:

К>Из языков на которых программирую, сложнее всего с управлением памятью в Оbjective-C — у Apple как обычно всё через задницу.


Как оно может быть сложнее С++, если там shared_ptr и weak_ptr встроены в язык?
Re[3]: c#
От: Константин Черногория  
Дата: 06.05.13 19:56
Оценка:
Здравствуйте, noone, Вы писали:

N>Как оно может быть сложнее С++, если там shared_ptr и weak_ptr встроены в язык?


C++
Опасные вещи, такие как операторы new/delete нужны крайне редко.
Если в полях объекта только smart pointers и generic collections, то при удалении объекта все его поля удалятся автомагически.
Если конструировать top-level objects только на стеках – вам вообще не нужно заниматься управлением памятью, за вас всё сделают язык, компилятор и библиотеки.

Obj-C
Даже при использовании рекомендуемой практики @property(retain), если вы забыли освободить какое-то поле в методе -(void)dealloc, вот она утечка.
Случайно сослались на self в блоке — получили циклическую ссылку.
Более безопасных альтернатив не существует.
Re[15]: c#
От: Ночной Смотрящий Россия  
Дата: 06.05.13 20:01
Оценка:
Здравствуйте, noone, Вы писали:

N>То, что можно обойтись без чего угодно, я знаю. Вернемся к исходному вопросу: могу ли я сохранить объект, который мне пришел в метод/функцию, или нет? И что делать, когда объект точно нужен, но сохранять его нельзя, т.к. есть вероятность цикла? Правильно: перепиливаем архитектуру, добавляем хаки по вкусу. Или используем GC.


Тут суть не столько в Publisher/Subscriber, сколько в замыканиях. И таки да, известный факт — без GC замыкания неюзабельны.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.