Hallo Karl,
du kannst das einfach so machen, wie du selbst eingangs beschrieben
hast. Das wäre in etwa:
1 | struct Thread
|
2 | {
|
3 | Thread(void(*f)(void*),void *data) ;
|
4 | } ;
|
5 | struct Foo
|
6 | {
|
7 | Thread thread ;
|
8 | Foo() : thread(&Foo::start,(void*)this) {}
|
9 | static void start(void *data) ;
|
10 | } ;
|
Thread ist hier eine Klasse die zum Ausführen asynchroner Funktionen
dient. Ob das nun ein RTOS Task (handle) ist, ein Posix Thread (handle)
oder was auch immer, typischerweise gibt es einen Einsprungspunkt (hier
start) und mindestens einen Parameter (hier die Instanz der Klasse).
Problematisch wird es wenn die start Funktion bereits auf die Instanz
zugreift, bevor diese überhaupt vollständig initialisiert ist. Im obigen
Beispiel kann das nicht passieren. In der Praxis hat man aber häufig
mehr als einen Parameter, und es ist nicht immer einfach umzusetzen,
dass der Thread-Aufruf erst am Ende der Initialisierungsliste ausgeführt
wird.
Komplizierter wird es zudem, wenn die Initialisierung nicht oder nicht
vollständig über die Initialisierungsliste geschieht, und wenn mit
Exceptions gerechnet werden muss.
Ein Lösungsansatz wäre das von mir oben beschriebene Verfahren: Erzeuge
die Instanz mit "leerem" Thread, und starte den Thread danach.
1 | struct Foo
|
2 | {
|
3 | Thread* thread ;
|
4 | Foo() : thread(nullptr) {}
|
5 | static void start(void *data) ;
|
6 | } ;
|
7 | Foo* make()
|
8 | {
|
9 | auto foo = new Foo() ;
|
10 | foo->thread = new Thread(start,(void*)foo) ;
|
11 | return foo ;
|
12 | }
|
Jetzt wird die Instanz ohne Thread erzeugt, und der Thread im Anschluss
gestartet. Das hat allerdings den Nachteil, dass der Benutzer immer mit
zwei Zuständen von Foo rechnen muss (mit oder ohne gestarteten Thread).
Also versteck man den Constructor und macht nur die make Funktion
sichtbar.
1 | struct Foo
|
2 | {
|
3 | static Foo* make() ;
|
4 | private:
|
5 | Thread* thread ;
|
6 | Foo() : thread(nullptr) {}
|
7 | static void start(void *data) ;
|
8 | } ;
|
Die Klasse "Thread" dient hier lediglich als generischer Platzhalter.
Diese kannst du durch den RTOS Task ersetzen.
Karl schrieb:
> Was bedeutet hier auto?
http://en.cppreference.com/w/cpp/language/auto
Karl schrieb:
> Diese Zeile verstehe ich eigentlich nicht.
> foo->thread = new Thread(start,(void*)foo) ;
Typischerweise werden Threads mit einer Start-Funktion (start) und einem
Zeiger auf Daten aufgerufen (hier die Instanz der Klasse Foo). Wie du
das als RTOS Taks abbildest, musst du wissen. Auf Anhieb sehe ich die
Parameter pvTaskCode und pvParameters.