Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> async+future+уведомление 
:(
    Опции темы
borisbn
Дата 26.2.2012, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Здравствуйте.

Нет ли стандартного способа вызвать функцию по окончании работы функции, переданной в async? Желательно, чтобы в функцию-уведомление передалось бы в качестве параметра возвращаемое значение функции из async.

Спасибо. 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 26.2.2012, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



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


PM WWW   Вверх
boostcoder
Дата 26.2.2012, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



хотя...вроде бы есть такая возможность, путем использования packaged_task::make_ready_at_thread_exit()
но проблема в том, что make_ready_at_thread_exit() еще не реализован. даже декларации нет. smile 
но в доках он присутствует: тыц и тыц.
PM WWW   Вверх
borisbn
Дата 27.2.2012, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Я тут повелосипедировал немного... Глянешь на досуге ? Покритикуешь ?
Код

namespace Async {

template< class Res >
void async_p( std::function< Res() > worker, std::function< void(Res) > waiter
            , typename std::enable_if< ! std::is_void< Res >::value >::type * p = 0 )
{
    waiter( worker() );
}

template< class Res >
void async_p( std::function< void() > worker, std::function< void() > waiter
            , typename std::enable_if< std::is_void< Res >::value >::type * p = 0 )
{
    worker();
    waiter();
}

template< class Waiter, class ... Args >
std::future< void > run( Waiter bound_waiter, Args ... args )
{
    typedef decltype( std::bind( args... )() ) Worker_Res;
    std::function< Worker_Res() > worker = std::bind( args... );
    return std::async( async_p< Worker_Res >, worker, bound_waiter, nullptr );
}

template< class Worker_Res, class Waiter, class ... Args >
std::future< void > run( void (Waiter::*waiter_f)(Worker_Res), Waiter waiter, Args ... args )
{
    std::function< Worker_Res() > worker = std::bind( args... );
    std::function< void(Worker_Res) > bound_waiter =
        std::bind( waiter_f, waiter, std::placeholders::_1 );
    return run( bound_waiter, args... );
}

template< class Waiter, class ... Args >
std::future< void > run( void (Waiter::*waiter_f)(), Waiter waiter, Args ... args )
{
    std::function< void() > worker = std::bind( args... );
    std::function< void() > bound_waiter = std::bind( waiter_f, waiter );
    return run( bound_waiter, args... );
}

} // namespace Async {

using std::cout;
using std::endl;

class Worker {
public:
    std::string work( const std::string & str, int x ) {
        cout << "Worker::work( " << str << ", " << x << " );" << endl;
        return str;
    }
};

class Waiter {
public:
    void onFinish( const std::string & str ) {
        cout << "Waiter::onFinish( " << str << " );" << endl;
    }
    void onFinish_v() {
        cout << "Waiter::onFinish( void );" << endl;
    }
};

void onFinish( const std::string & str ) {
    cout << "::onFinish( " << str << " );" << endl;
}

void work() {
    cout << "__work__( " << endl;
}

void onFinish_v() {
    cout << "::onFinish( void  );" << endl;
}


Worker worker;
Waiter waiter;

int main()
{
    auto f_v = Async::run( &Waiter::onFinish_v, waiter, work );
    auto f_x = Async::run( onFinish_v, work );
    auto f_0 = Async::run( onFinish, &Worker::work, worker, "str for worker 0", 42 );
    auto f_1 = Async::run( &Waiter::onFinish, waiter, &Worker::work, worker, "str for worker 1", 421 );
   
    f_1.wait();
    f_0.wait();
    f_x.wait();
    f_v.wait();
}

http://liveworkspace.org/code/5f5fc2a2f050...53d8d49fddc85b9


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 28.2.2012, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



borisbn, так а цель была, уйти от явного использования bind() ?
PM WWW   Вверх
borisbn
Дата 28.2.2012, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  28.2.2012,  14:33 Найти цитируемый пост)
цель была, уйти от явного использования bind() ? 

Ага. В том числе. Хочу, чтобы мои функции выглядели для пользователя как тот же std::thread или std::async...
К тому же если рабочая функция возвращает значение, то функции-уведомлению нужно делать std::bind с placeholder'ом, а если нет - то без него. А так получается единообразно.

Ну, а основная цель - сделать async-вызов с уведомлением. В принципе, я её достиг, но меня смущает то, что пользователь должен получать std::future и в конце программы (например, в деструкторе основного класса) ожидать её. Хотелось бы и этот процесс автоматизировать, но я пока не придумал как. Есть идея создать статический глобальный класс, который будет получать эти future'зы, складывать в список, а в своём деструкторе - ждать всех по-очереди... Бррр... самому не нравится


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0722 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.