Эквивалентен window.setTimeout () для C ++

В javascript есть сладкая функция window.setTimeout( func, 1000 ) ;, которая асинхронно вызывает func через 1000 мс.

Я хочу сделать что-то подобное в C ++ (без многопоточности), поэтому я собрал образец цикла, например:

    #include <stdio.h>

    struct Callback
    {
      // The _time_ this function will be executed.
      double execTime ;

      // The function to execute after execTime has passed
      void* func ;
    } ;

    // Sample function to execute
    void go()
    {
      puts( "GO" ) ;
    }

    // Global program-wide sense of time
    double time ;

    int main()
    {
      // start the timer
      time = 0 ;

      // Make a sample callback
      Callback c1 ;
      c1.execTime = 10000 ;
      c1.func = go ;

      while( 1 )
      {
        // its time to execute it
        if( time > c1.execTime )
        {
          c1.func ; // !! doesn't work!
        }

        time++;
      }
    }

Как я могу заставить что-то подобное работать?


person bobobobo    schedule 20.03.2010    source источник
comment
Вы ищете функцию sleep ()?   -  person just_wes    schedule 21.03.2010
comment
Не совсем. Я хочу, чтобы программа продолжала работать и перезвонила позже   -  person bobobobo    schedule 21.03.2010
comment
Это действительно не должно зависеть от платформы.   -  person bobobobo    schedule 21.03.2010
comment
Вопрос действительно касается выделенной жирным шрифтом строки, c1.func не вызывает функцию, похоже, она ничего не делает!   -  person bobobobo    schedule 21.03.2010
comment
Оглядываясь назад на это сейчас, боже мой, я был таким нубом. Скобки, скобки!   -  person bobobobo    schedule 07.12.2013


Ответы (5)


Сделайте Callback::func типа void (*)(), т.е.

struct Callback
{
    double execTime;
    void (*func)();
};

Вы можете вызвать функцию так:

c1.func();

Кроме того, не делайте этого - ждите. Используйте ualarm в Linux или _ 6_ в Windows.

person avakar    schedule 20.03.2010

После выхода C ++ 11 и при использовании компилятора, поддерживаемого C ++ 11, вы можете использовать лямбда, функцию вариативного шаблона и асинхронный поток , чтобы легко имитировать функцию javascript в c ++.

Вот код, который я написал для setTimeOut, он полностью протестирован:

Определение функции setTimeOut:

    #include <windows.h>//different header file in linux
    #include <future>
    using namespace std;

    template <typename... ParamTypes>
    void setTimeOut(int milliseconds,std::function<void(ParamTypes...)> func,ParamTypes... parames)
    {   
        std::async(std::launch::async,[=]()
        {       
            Sleep(milliseconds);
            func(parames...); 
        });
     };

Эта функция принимает переменные аргументы с помощью вариативного шаблона c + 11. Код может показать вам, как его использовать:

    #include <iostream>
    #include <thread>
    #include <string>
    #include <functional>
    #include <windows.h>

    #include <future>
    using namespace std;
    int main() 
    {
        std::mutex locker;
        std::function<void()> func1 = [&]()
        {
            std::unique_lock<std::mutex> lk(locker);
            std::cout << "func 1 is trigged:" << "   no parameter" << std::endl;
            lk.unlock();
        };      
        std::function<void(int)> func2 = [&](int param)
        {
            std::unique_lock<std::mutex> lk(locker);
            std::cout << "func 2 is trigged:" << "   int: " << param <<std::endl;
            lk.unlock();
        };
        std::function<void(int,std::string)> func3 = [&](int param1,std::string param2)
        {
            std::unique_lock<std::mutex> lk(locker);
            std::cout << "func 3 is trigged:" << "   int: " << param1 << ";  string: " << param2 << std::endl;
            lk.unlock();
        };

        for(int index=0;index<100;index++)
        {
            std::unique_lock<std::mutex> lk1(locker);
            std::cout << "set timer for func  1" << std::endl;
            lk1.unlock();
            setTimeOut<>(1000,func1);

            std::unique_lock<std::mutex> lk2(locker);
            std::cout << "set timer for func  2" << std::endl;
            lk2.unlock();
            setTimeOut<int>(2000,func2,10000);

            std::unique_lock<std::mutex> lk3(locker);
            std::cout << "set timer for func  3" << std::endl;
            lk3.unlock();
            setTimeOut<int,std::string>(5000,func3,10000,"ddddd");
        }
        Sleep(10000000);
    }
person Gisway    schedule 06.12.2013
comment
Я бы предложил использовать thread и chrono для сна, как описано здесь: stackoverflow.com/a/10613664/1922713 - person Max Strater; 02.08.2017
comment
Как отправить функцию-член или статическую функцию вместо std :: function в setTimeOut? - person Ambroise Rabier; 26.01.2018

В C ++ вы довольно ограничены. Вам нужна либо многопоточная ОС, в которой вы могли бы использовать функцию сна (вы все равно можете продолжить работу программы с отдельным потоком), либо вам нужна система обмена сообщениями, такая как Windows.

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

person Marty Fried    schedule 20.03.2010
comment
Ага! Это то, что я пытаюсь сделать. - person bobobobo; 21.03.2010

Я здесь только исправляю ваш код, а не мыслию нестандартно. Другие ответы уже дали некоторые указания на это.

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

  // The function to execute after execTime has passed
  void (*func)() ;

Затем назовите его так:

  c1.func() ;
person Thomas    schedule 20.03.2010
comment
Или вы можете использовать (* c1.func) (). Обычно я использую этот синтаксис с указателями на функции. Кроме того, я думаю, что c1.func = & go легче читать. - person Mr.Ree; 21.03.2010

Другой (лучший) ответ - использовать заголовок <functional> в C ++ и объявить функцию следующим образом:

#include <functional>

function<void ()> func ;

// assign like
func = go ; //go is a function name that accepts 0 parameters
// and has return type void

// exec like
func() ;
person bobobobo    schedule 14.12.2011