Ich bin manchmal echt dämlich!
Ich arbeite derzeit auf 64 Bit Gentoo Linux. Laufen soll das letzten Endes aber auf einem Raspi.
Sind ja schon interessante Ideen dabei. Das mit Threat klingt interessant.
Danke schonmal.
Ich bin manchmal echt dämlich!
Ich arbeite derzeit auf 64 Bit Gentoo Linux. Laufen soll das letzten Endes aber auf einem Raspi.
Sind ja schon interessante Ideen dabei. Das mit Threat klingt interessant.
Danke schonmal.
Ich hab mal auf die schnelle was zusammengeschrieben, ist jetzt aber mit Visual Studio 2015:
mitCode:// WorkerThread.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" std::mutex g_mutex; void console_out(const std::string& text) { std::lock_guard<std::mutex> lock(g_mutex); std::cout << text << std::endl; } class Worker { private: bool m_Run; int m_Counter; public: Worker() : m_Run(true), m_Counter(0) {} void Stop() { m_Run = false; } void Reset() { m_Counter = 0; } void operator()() { while (m_Run) // Hier ist die "Loop" ! { console_out(std::to_string(m_Counter++)); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } } }; int main() { Worker worker; std::thread t(std::ref(worker)); for (;;) { std::string input; std::getline(std::cin, input); if (input == "exit") { worker.Stop(); break; } else if (input == "reset") { worker.Reset(); } else { console_out("unknown command"); } } if (t.joinable()) { t.join(); } return 0; }
Code:// stdafx.h: Includedatei für Standardsystem-Includedateien // oder häufig verwendete projektspezifische Includedateien, // die nur in unregelmäßigen Abständen geändert werden. // #pragma once #include "targetver.h" #include <tchar.h> // TODO: Hier auf zusätzliche Header, die das Programm erfordert, verweisen. #include <string> #include <mutex> #include <thread> #include <iostream>
Geändert von Mxt (23.01.2016 um 12:03 Uhr) Grund: Kommentar zur Loop eingebaut
gerade auf dem Raspi (Raspbian Jessie) hab ich einiges (!!!) an source codes durchgetestet, bis was funktionierendes dabei war.
Letztlich funktioniert hat dieses hier:
Testcode:Code:/* * rpiconio.h * mimics kbhit(), getch() */ #ifndef RPICONIO_H #define RPICONIO_H #include <stdbool.h> #include <stdio.h> #include <string.h> #include <termio.h> #include <unistd.h> bool kbhit(void) { struct termios original; tcgetattr(STDIN_FILENO, &original); struct termios term; memcpy(&term, &original, sizeof(term)); term.c_lflag &= ~ICANON; tcsetattr(STDIN_FILENO, TCSANOW, &term); int characters_buffered = 0; ioctl(STDIN_FILENO, FIONREAD, &characters_buffered); tcsetattr(STDIN_FILENO, TCSANOW, &original); bool pressed = (characters_buffered != 0); return pressed; } void echoOff(void) { struct termios term; tcgetattr(STDIN_FILENO, &term); term.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &term); } void echoOn(void) { struct termios term; tcgetattr(STDIN_FILENO, &term); term.c_lflag |= ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &term); } #endif
Code:#include <stdio.h> #include <string.h> #include <unistd.h> #include <wiringPi.h> #include "rpiconio.h" int main(void) { long i=0; echoOff(); int c = '\0'; while (c != 'q') { if (kbhit()) { c = getchar(); printf("(hier ggf. auskommentieren:) got key \'%c\'\n", c); if(c==27) { printf("\nuser break\n"); return 1; } } printf("%ld\n", ++i); delay(100); } echoOn(); return 0; }
Geändert von HaWe (23.01.2016 um 16:13 Uhr) Grund: falsch reinkopiert)
Das mit Thread scheint ja ganz gut zu funktionieren und gefällt mir prinzipiell auch ganz gut.
Nur kann man von dem einen Thread auch etwas in einen anderen schreiben?
Ja, im Prinzip schon.
Dabei muss man zwei Dinge beachten. Einmal müssen die Daten natürlich sichtbar sein. Globale Variablen sind ja bei größeren Programmen eher verpöhnt. Man kann aber z.B. sowas machen
Dann ist da noch das Problem, dass mehrere Prozessorkerne auf die selben Daten lesend oder schreibend zugreifen wollen.Code:class Dings { // irgendwelche gemeinsamen Daten, die auch noch andere verwenden }; class Worker { // ... explicit Worker(Dings ding) // ob man hier kopiert oder mit Referenz oder (Smart-)Pointer arbeitet hängt von der Anwendung ab // Das explicit sagt: Ein Worker kriegt ein Ding. Ein Ding ist aber kein Worker. // Gegenbeispiel: Bruchzahl(int i) Ein int ist auch eine Bruchzahl // (Das ist nur bei Konstruktoren mit einem Parameter relevant) // ... int main() // ... Dings zeug; // Wird auch noch von anderen benutzt Worker worker(zeug); std::thread t(std::ref(worker)); // std::thread legt eine Kopie seiner Parameter an, // das std::ref packt worker in einen reference_wrapper // dadurch arbeitet der Thread auf dem selben Objekt wie main
Bei bool oder int ist das kein Problem
https://de.wikipedia.org/wiki/Cache-Koh%C3%A4renz
Schon bei einem string würde es knallen. Deshalb auch diese Funktion zur Consolenausgabe mit dem lock_guard.
Das alles zu erklären, würde etwas lang werden. Hier mal was es zu threads im Standard gibt
http://en.cppreference.com/w/cpp/thread
außerdem gibt es noch atomare Werte, die nur am Stück geändert werden können
http://en.cppreference.com/w/cpp/atomic
Geändert von Mxt (24.01.2016 um 08:26 Uhr)
Danke. Bisher funktioniert das ganz gut muss ich sagen!
wenn was "mal ne Zeitlang" gutgeht, heißt das nicht, dass es immer so sein wird. Meist gehen solche Sachen genau dann schief, wenn sie den größtmöglichen Schaden anrichten (acc to Murphy's Law (2) ).
Ganz persönlich finde ich: auf Multi-User-Multi-Tasking-OS in mehreren Tasks auf dieselben Ressourcen zuzugreifen ohne Mutexe zu benutzen - DAS finde ICH ziemlich "hirnfrei"![]()
Was immer diese Antwort bedeuten mag. Ein std::mutex ist ein solcher.
Bei int oder bool kann man noch volatile davorschreiben, muss man aber bei den meisten Compilern nicht.
Atomic ist in der Tat lock free programming und basiert auf memory order. Wenn man nicht gerade Hochfrequenz Börsenhandel (mittlerweile eine der größten C++ Anwendungen) betreibt, sollte man da besser als Anfänger von Abstand nehmen.
Lesezeichen