2010-03-20 15 views
5

En javascript hay este dulce función, dulce window.setTimeout(func, 1000) ; que de forma asíncrona invocar func después de 1000 ms.Equivalente a window.setTimeout() para C++

Quiero hacer algo similar en C++ (sin multithreading ), por lo que poner juntos un bucle de muestras como:

 
    #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++; 
     } 
    } 

¿Cómo puedo hacer algo como esto?

+0

¿Es la función sleep() lo que está buscando? –

+0

No realmente.Quiero que el programa continúe ejecutándose y llamar de nuevo más tarde – bobobobo

+0

¿En qué plataforma estás? – avakar

Respuesta

4

Hacer Callback::func de tipo void (*)(), es decir

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

Puede llamar a la función de esta manera:

c1.func(); 

Además, no ocupado: espere. Use ualarm en Linux o CreateWaitableTimer en Windows.

+0

Ah, buen punto sobre 'CreateWaitableTimer' – bobobobo

1

En C++ solo, eres bastante limitado. Necesita un sistema operativo de subprocesos múltiples, donde podría usar una función de suspensión (aún puede hacer que el programa continúe ejecutándose con un subproceso separado), o necesita un sistema de mensajería, como Windows.

La única otra forma en que veo que puede hacer algo es tener muchas llamadas dispersas por el código que llaman a una función que devuelve verdadero o falso, según haya transcurrido el tiempo. La función podría, por supuesto, ser una devolución de llamada, pero aún tendría que llamarla periódicamente.

+0

¡Sí! Esto es lo que trato de hacer. – bobobobo

1

Solo estoy arreglando su código aquí, sin pensar en nada más. Las otras respuestas ya dieron algunos consejos para eso.

Para una mejor seguridad de tipos, se debe declarar el puntero de devolución de llamada de la siguiente manera:

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

A continuación, llamar como:

c1.func() ; 
+0

¡Y usted señor, ha respondido la pregunta! ty. – bobobobo

+0

O puede usar (* c1.func)(). Usualmente uso esa sintaxis con punteros a las funciones. Además, creo que "c1.func = & go" es más claro de leer. –

+0

Ambos son buenos puntos. – Thomas

0

Otro (mejor) la respuesta sería utilizar el encabezado <functional> en C++, y declarar la función como tal:

#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() ; 
7

Después de que salió C++ 11, y si su están usando el compilador compatible C++ 11, puede usar lambda, función de plantilla variadic y subproceso asíncrono para simular fácilmente la función javascript en C++.

Este es el código que escribí para setTimeOut, que está completamente probado: definición

setTimeOut del funtion:

#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...); 
     }); 
    }; 

Esta función acepta argumentos variables mediante el uso de c + plantilla variadic de 11, El código puede le mostrará cómo usarlo:

#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); 
    } 
+0

Sugeriría usar 'thread' y' chrono' para dormir como se describe aquí: https://stackoverflow.com/a/10613664/1922713 –

+0

¿Cómo se envía la función miembro o la función estática en lugar de std :: function a setTimeOut? –