C++ の window.setTimeout() と同等
-
21-09-2019 - |
質問
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 ;//!!機能しません! } time++; } }
このようなものを機能させるにはどうすればよいでしょうか?
解決
作る Callback::func
タイプの void (*)()
, 、つまり
struct Callback
{
double execTime;
void (*func)();
};
この関数は次のように呼び出すことができます。
c1.func();
また、忙しく待たないでください。使用 ualarm
Linux または CreateWaitableTimer
Windows 上で。
他のヒント
C++11 が登場した後、C++11 がサポートするコンパイラを使用している場合は、次のコマンドを使用できます。 ラムダ, 可変個引数テンプレート関数 そして 非同期スレッド C++ で JavaScript 関数を簡単にシミュレートします。
これは私が 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);
}
でC ++自体によって、あなたはかなり限られています。あなたは(あなたがまだプログラムが別のスレッドで実行し続けていることができます)あなたはスリープ機能を使用することができ、マルチスレッドOS、どちらかを必要とするか、Windowsのようなメッセージングシステムを、必要があります。
私はあなたが何かを行うことができていることがわかり唯一の他の方法は、trueまたはfalseを返しますが、時間が経過したかどうかに応じて、その関数を呼び出すコードに散在呼び出しの多くを持つことです。関数は、当然のことながら、コールバックかもしれないが、あなたはまだ定期的にそれを呼び出す必要があります。
私はボックスの外側を考えていない、ここにコードを修正しています。他の回答には、すでにそのためのいくつかのポインタを与えます。
次のように優れたタイプの安全のために、あなたはコールバックポインタを宣言する必要があります:
// The function to execute after execTime has passed
void (*func)() ;
次に、としてそれを呼び出します
c1.func() ;
別の(よりよい)答えはC ++で<functional>
ヘッダを使用することなどのような機能を宣言します。
#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() ;