2016-05-22 3 views
4

У меня есть поток, который берет каждый элемент из контейнера и отправляет запрос на загрузку в базу данных. Загрузка выполняется синхронно.std :: future или std :: shared_future для ожидания нескольких потоков

Элементы в контейнере - это финансовые контракты, и они могут иметь или не иметь связанный с ним тикет данных.

Теперь для тех контрактов, у которых есть тикпинг, я должен выполнить двухпроходную загрузку. 1) сначала загрузите тик-файл в db. db возвращает идентификатор. 2) Прикрепите идентификатор к контракту, а затем загрузите контракт.

Так, например, если я зацикливаю контейнер, имеющий 100 контрактов, скажем, 30 из них имеют тикпинг, а остальные 70 нет.

Я пытаюсь выяснить, подходит ли std::future или std::shared_future для такой задачи?

Я попытался реализовать, имея будущее, связанное с каждым из 30 контрактов, и вызовет std :: async с запуском: политика async. Таким образом, в первом проходе цикла запускаются потоки 3o, а возвращаемое будущее «перемещается» в контейнер, связанный с контрактом. Остальные 70 контрактов просто загружены обычным способом.

На втором переходе я надеюсь позвонить get() в сохраненное будущее. Если запрос завершен, получите идентификатор и завершите загрузку с ним. Вероятно, это не сработает, потому что я думаю, что перемещение будущего в контейнер отделит поток.

Просьба сообщить, какой подход я должен предпринять, чтобы реализовать поведение, которое я хочу?

+0

Они выполнены синхронно? Вы узнаете ответ, когда он закончит. – erip

+0

Возможно, вы могли бы каждый рабочий поток опубликовать свои результаты в потокобезопасную очередь, когда она будет завершена? –

+0

Почему бы не хранимая процедура не вставляла тикет и договор вместе? Какая польза от их разделения? – ildjarn

ответ

0

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

Ваши тикающие решения выглядят как будущие фьючерсы - одно будущее для загрузки по тику, одно для загрузки контракта. Но будущее будущее - это будущее в некотором смысле.

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

Предположим, у вас есть тип контракта Contract (который я буду считать псевдорегулярным). Привязка к вашему тикающему идентификатору - операция типа function<void(Contract&)>. Любопытно, что такая операция может быть и пустой.

У нас есть std::future<void(Contract&)> Contract::PrepareForUpload() const. Для каждого контракта, который вы хотите загрузить, ищите его.

те, у кого есть знак возврата std::async сгенерированный future, которому принадлежит нить.

те, у кого нет тикового возврата, отложен std::async с noop []{return [](auto&&...){};} завод.

Затем добавьте std::future<void> Contract::Upload(std::function<void(Contract&>) const, который запускает код подготовки, а затем загружает (зачем это здесь? Я покажу позже).

Теперь операция загрузки является:

auto prep = contract.PrepareForUpload(); 
auto upload = contract.Upload(prep.get()); 

Теперь это немного раздражает. Выполнение двух вещей? Ик.

Почему бы нам не сделать это?

std::future<void> Contract::Upload() const { 
    return std::async(
    std::launch::async, 
    [this]{ 
     auto prep = contract.PrepareForUpload(); 
     return contract.Upload(prep.get()); 
    } 
); 
} 

и теперь Contract::Upload автоматически делает ПОДГОТОВКУ и загрузку для вас.

Это, однако, запускает 2 трека в тик-сейфе. Поэтому напишите синхронный PrepareForUpload, который можно вызвать в «сложенном» Upload корпусе.

Если PrepareForUpload нужны дополнительные аргументы, мы можем передать их Upload.

Возможно, детали, которые вы не написали, могут сделать этот трюк, но правильный ответ на цепочку фьючерсов, как правило, сводит цепочку в одно будущее.

У C++ 1z есть предложения по применению .then и аналогичные функции, чтобы сделать такое сведение коллапса простым и эффективным.

+0

спасибо @Yakk. Ничего себе, здорово знать о возможности свести будущее в будущее! Однако мое требование было немного проще. Выгрузка контрактов не должна была быть асинхронной. Поэтому в основном, когда я просматриваю первый цикл, я сохраняю вектор будущего, связанный с идентификатором контракта для всех загружаемых запросов на загрузку таблицы async, которые были опубликованы. И затем во втором проходе я получаю get() для всех элементов вектора, получаю тик-таблицу в обратном порядке, а затем используя идентификатор контракта, связанный с каждым элементом, вставляю ticktableid в контракт и выполняю синхронную загрузку. – user2930006

Смежные вопросы