2017-04-18 16 views
2

Also wollte ich mich herausfordern, indem ich einen kleinen threadpool in C++ schreibe, und ich wollte versuchen, die einfach zu bedienende Art und Weise, mit der std :: thread arbeiten, zu können Erstelle einen Thread und als Parameter sende eine Funktion und Parameter für diese Funktion, verglichen mit etwas wie pthreads, die dich zwingen, eine void * als einzige Indata für die Funktion zu haben.C++ speichern Funktion und Parameterliste für die spätere Verwendung

Bis jetzt konnte ich Vorlagen und Parameterpakete verwenden, um eine Funktion zu erstellen, die eine andere Funktion und Parameter dafür übernehmen und ausführen kann, aber ich finde keine Möglichkeit, sie zu speichern, so dass ich sie ausführen kann zu einem späteren Zeitpunkt (wenn es einen freien Thread im Threadpool gibt). Ich habe versucht, std :: function zusammen mit std :: tuple und std :: bind zu verwenden, aber da ich nicht genau weiß, mit welchen Typen ich es zu tun habe, kann ich keine Möglichkeit finden, die Funktion und die Parameter zu speichern damit ich sie später in einem anderen Teil meines Codes verwenden kann, da ich an diesem Punkt nicht mehr weiß, aus welchen Typen alles besteht. Unten ist ein Code, mit dem ich herumgespielt habe, der helfen könnte zu zeigen, wie ich meine.

template<typename Function, typename... Arguments> 
void TestFunction(Function func, Arguments... parameters) 
{ 

std::function<std::result_of<Function(Arguments...)>::type(Arguments...)>* tempFunc; 
tempFunc = new std::function<std::result_of<Function(Arguments...)>::type(Arguments...)>(func); 
void* funcPtr = tempFunc; 
std::tuple<Arguments...>* tempTuple; 
tempTuple = new std::tuple<Arguments...>(parameters...); 
void* tuplePtr = tempTuple; 

//func(parameters...); 
(Arguments...)>*)funcPtr, *(std::tuple<Arguments...>*)tuplePtr); 

auto bindTest = std::bind(func, parameters...); 
bindTest(); 
void* bindPtr = &bindTest; 

} 

int main() 
{ 
TestFunction(std::printf, "%d, %d, %d\n", 3, 2, 1); 

getchar(); 
return 0; 
} 

Es könnte sein, dass es nicht möglich ist, zu tun, was ich tun möchte, und in diesem Fall denke ich, werde ich nur mehr wie pThreads zu einem Ansatz wechseln. Aber wenn jemand eine Arbeit kennt, wäre ich dankbar.

+0

Haben Sie Lambdas probiert? Es kann Funktionsaufruf und Parameter ohne irgendein Problem speichern. –

+0

@MichaelNastenko Ich habe in sie geschaut, aber das Problem, wie man sie in einem allgemeinen Sinn speichert, gilt auch für sie – Gamewolf3000

+0

Sie können 'std :: packaged_task' in Lambda und es wird kümmern sich um die Speicherung von Parametern und die Rückgabe von Wert. –

Antwort

2

Der Schlüssel ist, dass Sie den Rückgabetyp von Std :: Bind in einer Std :: -Funktion speichern können. Weil std :: bind ein Objekt zurückgibt, das aufrufbar ist. Sie sollten dann in der Lage sein, die Instanz std :: function abhängig davon zu speichern, wie Sie den Rückgabetyp behandeln möchten.

template<typename Function, typename... Arguments> 
void TestFunction(Function func, Arguments... parameters) 
{ 
    using Ret = typename std::result_of<Function>::type; 
    std::function<Ret()> val{std::bind(func, parameters...)}; 
} 

Wenn Sie dies tun, wenn Sie zuerst die Funktion recive Sie nicht mehr über die Argumente Art zu denken, und nur den Rückgabetyp. Wie Sie mit dem Rückgabetyp umgehen, hängt vom Anwendungsfall ab, in dem die Funktion gespeichert wird. Ein einfacher Ansatz besteht darin, dass Function eine void-Funktion ist, was sinnvoll sein kann, wenn es keine Möglichkeit gibt, den Wert an den API-Konsumenten zurückzugeben.

+0

Das klingt nach einer anständigen Lösung, ich hätte gerne Rückgabewerte, aber ich könnte wahrscheinlich Ihren Weg gehen und einfach verschiedene Arten haben, die Standardtypen (wie int, float und char) zu speichern und den Benutzer nicht hereinlassen zu lassen Funktionen mit benutzerdefinierten Rückgabewerten. Ich nehme an, dass es dann keine Möglichkeit gibt, eine ganz allgemeine Funktion zu speichern? – Gamewolf3000

+0

@ Gamewolf3000 Wie planen Sie, den Rückgabewert an die Kunden von TestFunction zurückzugeben? Wenn Sie einen zukünftigen Wert direkt aus der Testfunktion zurückgeben möchten, können Sie die Funktion möglicherweise in eine void Callable umwandeln. Wenn Sie alternativ eine andere Funktion für die Klasse verwenden möchten, die die Funktion speichert, müssen Sie diese möglicherweise im Rückgabetyp parametrisieren. – user1937198

+0

Ursprünglich plante ich, eine Art Smart-Zeiger aus der Funktion der API zurückzugeben, von der Informationen über den Status der Aufgabe (Warten, Abgeschlossen usw.) abgerufen werden können, sowie einen Leerzeiger auf die Rückgabedaten.Aber je mehr ich darüber nachdenke, desto mehr fällt es auseinander, denn selbst wenn ich es verallgemeinern kann, dann stellt sich die Frage, wie man mit nicht dynamisch zugewiesenen Renditen umgehen soll (wer dafür verantwortlich ist). Es ist also wahrscheinlich besser, wenn Sie den Rückgabewert nicht erhalten und der Benutzer es umgeht, aber es wäre immer noch schön, irgendeine Art von Funktion zu haben – Gamewolf3000

Verwandte Themen