нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: ksd Россия  
Дата: 02.08.18 16:24
Оценка:
возможен ли готовый хороший субж в природе?
(вектор, лист, сет или их аналоги -- все подойдет)
Отредактировано 02.08.2018 16:25 ksd . Предыдущая версия .
Re: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: LaptevVV Россия  
Дата: 02.08.18 17:12
Оценка: -2
ksd>возможен ли готовый хороший субж в природе?
ksd>(вектор, лист, сет или их аналоги -- все подойдет)
А что такое неинвалидирующие итераторы?
А то в С++17 контейнеры уже сделаны потокобезопасными вроде.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: placement_new  
Дата: 02.08.18 17:23
Оценка:
Здравствуйте, LaptevVV, Вы писали:

ksd>>возможен ли готовый хороший субж в природе?

ksd>>(вектор, лист, сет или их аналоги -- все подойдет)
LVV>А что такое неинвалидирующие итераторы?
LVV>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.
Re[2]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: ksd Россия  
Дата: 03.08.18 09:35
Оценка:
Здравствуйте, LaptevVV, Вы писали:

ksd>>возможен ли готовый хороший субж в природе?

ksd>>(вектор, лист, сет или их аналоги -- все подойдет)
LVV>А что такое неинвалидирующие итераторы?
в треде 1 получаем итератор и перебираем элементы в контейнере, в треде 2 делаем insert или erase -- итератор в треде 1 не отваливается.


LVV>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.

это замечательно!
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: IID Россия  
Дата: 04.08.18 18:28
Оценка:
Здравствуйте, ksd, Вы писали:

LVV>>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.

ksd>это замечательно!

Внутренняя потокобезопасность это тормоза.
kalsarikännit
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: Mr.Delphist  
Дата: 06.08.18 16:23
Оценка:
Здравствуйте, ksd, Вы писали:

ksd>в треде 1 получаем итератор и перебираем элементы в контейнере, в треде 2 делаем insert или erase -- итератор в треде 1 не отваливается.


А теперь следующий вопрос: что должно произойти про инкременте/декременте этого итератора? От этого и плясать.
Re[4]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: sergey2b ЮАР  
Дата: 06.08.18 16:39
Оценка:
Здравствуйте, IID, Вы писали:

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


LVV>>>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.

ksd>>это замечательно!

IID>Внутренняя потокобезопасность это тормоза.


может у него в контейнере 100 элементов и обращения к нему пару раз в минуту
если это не так ТС написал об этом в первом сообщение
Re[2]: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: uzhas Ниоткуда  
Дата: 07.08.18 16:19
Оценка: +1
Здравствуйте, LaptevVV, Вы писали:

LVV>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.


о чем речь? что изменилось в плане потокобезопасности для старых контейнеров или какие-то новые контейнеры появились?
Re: нужен контейнер, потокобезопасный, с неинвалидирующимися ите
От: a7d3  
Дата: 07.08.18 16:30
Оценка: 4 (1)
Здравствуйте, ksd, Вы писали:

ksd>возможен ли готовый хороший субж в природе?

ksd>(вектор, лист, сет или их аналоги -- все подойдет)

Держи «Потокобезопасный std::map с производительностью lock-free map»
общая вводная по либе «Lock-free структуры данных. Извне: введение в libcds»
Re[5]: у него много обращений на чтение, и очень очень редко на запись
От: ksd Россия  
Дата: 08.08.18 09:44
Оценка:
Здравствуйте, sergey2b, Вы писали:

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


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


LVV>>>>А то в С++17 контейнеры уже сделаны потокобезопасными вроде.

ksd>>>это замечательно!

IID>>Внутренняя потокобезопасность это тормоза.


S>может у него в контейнере 100 элементов и обращения к нему пару раз в минуту

S>если это не так ТС написал об этом в первом сообщение
++ "у него" в контейнере ~10 элементов, но много обращений на чтение:
    struct Subsc_t {
        virtual void doSome() = 0;
    };

    set<Subsc_t*> subscribers;

    for (auto s: subscribers) {
        s->doSome();
    }

и с очень маленькой вероятностью в миллионы раз реже может быть из другого треда subscribers.insert(some) или erase;
завернуть for в критическую секцию не вариант.
Re: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: landerhigh Пират  
Дата: 08.08.18 11:30
Оценка: :)
Здравствуйте, ksd, Вы писали:

ksd>возможен ли готовый хороший субж в природе?


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

ksd>(вектор, лист, сет или их аналоги -- все подойдет)


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

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

for (auto i = container.begin(); i != container.end(); ++i)
{
    auto some_value = do_something_with(*i);
    call_some_other_code(some_value);
    // another 100500 lines of code
}


Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.
www.blinnov.com
Отредактировано 08.08.2018 11:39 landerhigh . Предыдущая версия .
Re[2]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: ksd Россия  
Дата: 08.08.18 12:13
Оценка:
Здравствуйте, landerhigh, Вы писали:

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


ksd>>возможен ли готовый хороший субж в природе?


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


ksd>>(вектор, лист, сет или их аналоги -- все подойдет)


L>Сферической потокобезопасности в вакууме не бывает. Ее можно натянуть на контейнеры, которые используются исключительно через операции единичной вставки/чтения (очередь, к примеру)


L>Попытка сделать "потокобезопасными" контейнеры, по которым необходимо итерироваться, в конечном итоге приводит к куче проблем и выкорчевыванию "изобретения" из проекта.


L>
L>for (auto i = container.begin(); i != container.end(); ++i)
L>{
L>    auto some_value = do_something_with(*i);
L>    call_some_other_code(some_value);
L>    // another 100500 lines of code
L>}
L>


L>Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.

это еще почему?! итератор может же в операторе ++ поинтересоваться, обновился контейнер или нет?
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: landerhigh Пират  
Дата: 08.08.18 12:58
Оценка:
Здравствуйте, ksd, Вы писали:

L>>Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.

ksd>это еще почему?! итератор может же в операторе ++ поинтересоваться, обновился контейнер или нет?

Может. Ну, допустим, обновился (если раньше не упадет, см. ниже). Дальше что?

Далее:

some_type do_something_with(const some_other_type& what)
{
    //....
}

for (auto i = container.begin(); i != container.end(); ++i)
{
    auto some_value = do_something_with(*i);      // А в этот прекрасный момент другой поток делает контейнеру clear()
}



Иными словами, попытка изобрести универсальный потокобезопасный контейнер ни к чему хорошему не приводит.
www.blinnov.com
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: Mr.Delphist  
Дата: 08.08.18 13:07
Оценка:
Здравствуйте, ksd, Вы писали:

ksd>это еще почему?! итератор может же в операторе ++ поинтересоваться, обновился контейнер или нет?


Ну, поинтересовался он. Услышал в ответ "вас тут не стояло", потому что контейнер с тех пор успели дважды очистить и заново наполнить. Что тогда делаем в плюс-плюсинге?
Re[4]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: · Великобритания  
Дата: 08.08.18 14:33
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

ksd>>это еще почему?! итератор может же в операторе ++ поинтересоваться, обновился контейнер или нет?

MD>Ну, поинтересовался он. Услышал в ответ "вас тут не стояло", потому что контейнер с тех пор успели дважды очистить и заново наполнить. Что тогда делаем в плюс-плюсинге?
В его случае самым оптимальным было бы снапшотиться, т.е. старый итератор должен будет продолжать обход старой коллекции. С случае наличия gc (в java) я бы делал так:

    volatile Set<Subsc_t> subscribers = Collections.emptySet();

public void doSome()
{//тут локи не нужны, т.к. коллекция никогда не меняется
    for (var s: subscribers) {
        s->doSome();
    }
}
public void add(Subscrber s)
{
    synchronized(lock) {
        var newSubscribers = new HashSet<>(subscribers);//потому что мы всегда создаём новую
        newSubscribers.add(s);
        subscribers = newSubscribers;
    }
}

Без gc что-то даже не знаю как это нормально сделать... Идеи?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: B0FEE664  
Дата: 09.08.18 08:03
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>
L>for (auto i = container.begin(); i != container.end(); ++i)
L>{
L>    auto some_value = do_something_with(*i);
L>    call_some_other_code(some_value);
L>    // another 100500 lines of code
L>}
L>


L>Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.


Представьте, что ваш контейнер — это база данных. Не существует баз данных, с которыми можно работать из нескольких потоков?
И каждый день — без права на ошибку...
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: a7d3  
Дата: 09.08.18 08:53
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

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


L>>
L>>for (auto i = container.begin(); i != container.end(); ++i)
L>>{
L>>    auto some_value = do_something_with(*i);
L>>    call_some_other_code(some_value);
L>>    // another 100500 lines of code
L>>}
L>>


L>>Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.


BFE>Представьте, что ваш контейнер — это база данных. Не существует баз данных, с которыми можно работать из нескольких потоков?


И тем не менее правда на стороне .
А все попытки натянуть сову на глобус с неуместными аналогиями — это просто капризы дилетантов, незнакомых с элементарными, базисными вещами. Тем, как именно, в какую сторону продумывается архитектура и взаимодействие со структурами данным в объектной модели малтитредового софта.
Из разряда: «да, мы пишем на С++, но давайте чтобы без эксепшенов, а то как-то сложно с ними получается».

Зачем цепляться за идиому итераторов в плане многопоточного доступа к контейнеру? Чтобы героически бороться с мельницами?
Что афтар топика решает своим итерированием по контейнеру? Делает последовательный проход, для чего? Чтобы последовательно вызвать несколько обработчиков/действий.
Не уж то это же самое нельзя сделать иначе как через последовательный доступ итератором?

Содержимое этого контенера — есть пачка заданий для треда, с вероятностью 1/(10³×10³) в процессе выполнения может потребоваться добавить или убрать что-то из этой пачки из другого треда. И что, это конец света? Иначе чем через итераторы не сделать?
Re[3]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: landerhigh Пират  
Дата: 09.08.18 09:04
Оценка:
Здравствуйте, B0FEE664, Вы писали:

L>>Код выше нельзя в общем случае сделать потокобезопасным средствами контейнера.

BFE>Представьте, что ваш контейнер — это база данных. Не существует баз данных, с которыми можно работать из нескольких потоков?

Речь идет о контейнерах.
Попытка сделать из контейнера базу данных с преферансом, барышнями и transaction isolation только потому, что авторам лень или не хватает терпения продумать архитектуру ведет к эпичному провалу более чем всегда.

Когда нужно именно хранилище с транзакционностью, со снапшотами и т.п., тогда и вопрос ставят именно так
www.blinnov.com
Re[5]: нужен контейнер, потокобезопасный, с неинвалидирующимися
От: landerhigh Пират  
Дата: 09.08.18 09:09
Оценка: +3
Здравствуйте, ·, Вы писали:

MD>>Ну, поинтересовался он. Услышал в ответ "вас тут не стояло", потому что контейнер с тех пор успели дважды очистить и заново наполнить. Что тогда делаем в плюс-плюсинге?

·>В его случае самым оптимальным было бы снапшотиться,

продумывать архитектуру.

Дело в том, что от постановки вопроса веет подходом "мы не знаем, сколько у нас будет потоков и вообще не подумали о межпоточном взаимодействии, поэтому нам нужен потокобезопасный контейнер".
Классический "Failing to plan is planning to fail".
www.blinnov.com
Re[6]: у него много обращений на чтение, и очень очень редко на запись
От: Кодт Россия  
Дата: 09.08.18 09:57
Оценка:
Здравствуйте, ksd, Вы писали:

ksd>++ "у него" в контейнере ~10 элементов, но много обращений на чтение:

ksd>и с очень маленькой вероятностью в миллионы раз реже может быть из другого треда subscribers.insert(some) или erase;
ksd>завернуть for в критическую секцию не вариант.

А завернуть в read-write lock — вариант?

В С++17 это называется std::shared_mutex.
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.