shared_ptr с версионностью
От: Аноним  
Дата: 30.11.09 00:51
Оценка:
Есть сервер. Потоки (отвечающие на запросы) используют для чтения некоторую структуру данных. Раз в час сервер обновляет эту структуру данных. Сейчас для обеспечения конкуррентной работы использую RWLock. (при чтении поток ставит read lock, при обновлении write lock). Всё работает нормально, но во время обновления структуры, новые запросы вынуждены ждать уже выполняющиеся, длинные запросы.
Для решения проблемы можно было бы в каждом потоке создавать копию этой структуры, но это может быть довольно накладно. По этому, предлагается следующее решение:
— может существовать несколько версий объекта;
— время жизни каждой версии управляется с помощью shared_ptr;
— для чтения объекта, берётся самая новая копия (метод const shared_ptr<T> get() const);
— для изменения объекта, создаётся новый объект (например, объект сначала копируется, затем модифицируется), и добавляется к списку версий (метод void replace(const T &));
— для того, чтобы запретить одновременное изменение объекта, можно использовать обычный mutex;
— список версий состоит из одного элемента — указателя на последнюю версию, для его изменения используется атомарный swap;
Реализовано ли это, например, в boost, или прийдётся писать велосипед (на первый взгляд, решение не сложное)?
Re: shared_ptr с версионностью
От: jazzer Россия Skype: enerjazzer
Дата: 30.11.09 02:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Реализовано ли это, например, в boost, или прийдётся писать велосипед (на первый взгляд, решение не сложное)?


Прямо в таком виде — нет, но, на первый взгляд, можно реализовать при помощи Boost.Flyweight (тебе понадобится своя factory, которая всегда будет отдавать только последнюю версию объекта).
http://www.boost.org/libs/flyweight/doc/index.html

Но и руками закодировать всю эту радость должно быть просто.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: shared_ptr с версионностью
От: jazzer Россия Skype: enerjazzer
Дата: 30.11.09 05:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>- список версий состоит из одного элемента — указателя на последнюю версию, для его изменения используется атомарный swap;


кстати, в новом стандарте у shared_ptr будут атомарные операции типа atomic_swap, так что не придется городить огород с мьютексами и дополнительными указателями.

последний драфт качать здесь: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf (номер легко запомнить, как специально подгадывали)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
c++0x draft standard working paper 2009
Re: shared_ptr с версионностью
От: Аноним  
Дата: 30.11.09 08:14
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть сервер. Потоки (отвечающие на запросы) используют для чтения некоторую структуру данных. Раз в час сервер обновляет эту структуру данных. Сейчас для обеспечения конкуррентной работы использую RWLock. (при чтении поток ставит read lock, при обновлении write lock). Всё работает нормально, но во время обновления структуры, новые запросы вынуждены ждать уже выполняющиеся, длинные запросы.

А>Для решения проблемы можно было бы в каждом потоке создавать копию этой структуры, но это может быть довольно накладно. По этому, предлагается следующее решение:

Может оно и нужно, но не в вашем случае.
Если обновления быстрые а чтение долгое, то делается очередь обновлений в которую кидаются обновления если структура занята, а потом любой поток в соответствии с приоритетами может выполнить ожидающие обновления.
Re[2]: shared_ptr с версионностью
От: remark Россия http://www.1024cores.net/
Дата: 02.12.09 11:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>Есть сервер. Потоки (отвечающие на запросы) используют для чтения некоторую структуру данных. Раз в час сервер обновляет эту структуру данных. Сейчас для обеспечения конкуррентной работы использую RWLock. (при чтении поток ставит read lock, при обновлении write lock). Всё работает нормально, но во время обновления структуры, новые запросы вынуждены ждать уже выполняющиеся, длинные запросы.

А>>Для решения проблемы можно было бы в каждом потоке создавать копию этой структуры, но это может быть довольно накладно. По этому, предлагается следующее решение:

А>Может оно и нужно, но не в вашем случае.

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

Это решит ровно ноль проблем и добавит новые. Нет никакой разницы, сделает обновление поток Q или поток W, обновляющему потоку всё равно придётся делать ту же самую плохую вещь — блокировать читающие потоки.
Плюс это ломает последовательную консистентность: если поток добавляет элемент в коллекцию, а потом ищет его, то он должен его находить. При использовании отложенного обновления поток может не найти элемент, который он только что вставил.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: shared_ptr с версионностью
От: remark Россия http://www.1024cores.net/
Дата: 02.12.09 11:20
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Есть сервер. Потоки (отвечающие на запросы) используют для чтения некоторую структуру данных. Раз в час сервер обновляет эту структуру данных. Сейчас для обеспечения конкуррентной работы использую RWLock. (при чтении поток ставит read lock, при обновлении write lock). Всё работает нормально, но во время обновления структуры, новые запросы вынуждены ждать уже выполняющиеся, длинные запросы.

А>Для решения проблемы можно было бы в каждом потоке создавать копию этой структуры, но это может быть довольно накладно. По этому, предлагается следующее решение:
А>- может существовать несколько версий объекта;
А>- время жизни каждой версии управляется с помощью shared_ptr;
А>- для чтения объекта, берётся самая новая копия (метод const shared_ptr<T> get() const);
А>- для изменения объекта, создаётся новый объект (например, объект сначала копируется, затем модифицируется), и добавляется к списку версий (метод void replace(const T &));
А>- для того, чтобы запретить одновременное изменение объекта, можно использовать обычный mutex;
А>- список версий состоит из одного элемента — указателя на последнюю версию, для его изменения используется атомарный swap;
А>Реализовано ли это, например, в boost, или прийдётся писать велосипед (на первый взгляд, решение не сложное)?

Список версий тут не нужен. Каждый старый объект может "доживать свой век" независимо от других объектов, просто когда последний читатель закончит работу с объектом, он удалит его.
Тут нужен просто shared_ptr+mutex:

mutex g_mtx;
shared_ptr<object_t> g_obj;

void reader_thread()
{
  for (;;)
  {
    g_mtx.lock();
    shared_ptr<object_t> obj = g_obj;
    g_mtx.unlock();
    // processing
  }  
}

void writer_thread()
{
  for (;;)
  {
    shared_ptr<object_t> obj = create_object();
    g_mtx.lock();
    g_obj = obj;
    g_mtx.unlock();
    sleep();
  }
}



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: shared_ptr с версионностью
От: jazzer Россия Skype: enerjazzer
Дата: 02.12.09 18:03
Оценка:
Здравствуйте, remark, Вы писали:

А>>- список версий состоит из одного элемента — указателя на последнюю версию, для его изменения используется атомарный swap;


R>Список версий тут не нужен.

Так он сам вроде к этому и пришел в результате, см. выделенное
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: shared_ptr с версионностью
От: remark Россия http://www.1024cores.net/
Дата: 03.12.09 08:20
Оценка:
Здравствуйте, jazzer, Вы писали:

А>>>- список версий состоит из одного элемента — указателя на последнюю версию, для его изменения используется атомарный swap;


R>>Список версий тут не нужен.

J>Так он сам вроде к этому и пришел в результате, см. выделенное

Ну может, не знаю, меня смутило:

для изменения объекта, создаётся новый объект, и добавляется к списку версий

Без списка тут и писать, и искать готовое нечего.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: shared_ptr с версионностью
От: jazzer Россия Skype: enerjazzer
Дата: 03.12.09 08:56
Оценка:
Здравствуйте, remark, Вы писали:

R>Без списка тут и писать, и искать готовое нечего.


Угу, особенно с С++0х-овым atomic_swap|atomic_store. Даже мьютексы никакие не нужны
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: shared_ptr с версионностью
От: remark Россия http://www.1024cores.net/
Дата: 03.12.09 09:10
Оценка:
Здравствуйте, jazzer, Вы писали:

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


R>>Без списка тут и писать, и искать готовое нечего.


J>Угу, особенно с С++0х-овым atomic_swap|atomic_store. Даже мьютексы никакие не нужны



Кстати, вот тут есть пример использования std::atomic_load/atomic_store для этой цели (раздел "Double-checked locking returns")
http://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-6-double-checked-locking.html



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.