wywołanie funkcji klasy w danym wątku, z innego wątku

0

Witam
Chcę napisac klasę, która będzie wykonywac sobie swoje obliczenia i będzie działac ona w jednym wątku. Będzie druga klasa ktora będzie wykonywac inne obliczenia w drugim watku, i bedzie trzeci watek, nadrzedny, ktory bedzie nadzorował pozostałe. Trzeci watek to bedzie interfejs aplikacji.
I teraz chciałbym, aby po nacisnieciu przycisku zakoncz, aplikacja miala mozliwosc zapisania stanu aktualnych obliczen. Aby mozna bylo z watku nadrzednego wywolac funkcje, np. Pause(), GetCurrentResults(), a dopiero potem zabic te watki. Wynik zapisac i zamknac aplikacje.
chce aby wykorzystana do tego biblioteka, lub funkcjonalnosc, dzialala na windowsie i linuksie.
prosze o pomoc i podpowiedzi:)

0

boost::thread :)

a tak w ogole to jedyne czego potrzebujesz to to, aby trzeci watek znal wskazniki/referencje na te dwa obiekty pozostale. to ze defacto one beda mialy jakis jeszcze drugi i trzeci niezalezny tok wykonywania, to nic nie zmienia - watek trzeci bedzie korzystal z tych obiektow tak jak ze zwyklych..

0

Do takich prostych rzeczy jak zatrzymanie wątku nie potrzeba synchronizacji. Wystarczy jedna zmienna mówiąca o tym, czy wątek ma się wykonywać czy nie. Można ją używać bezpiecznie z poziomu każdego wątku, bo odczyt czy zapis jest jednym rozkazem, co za tym idzie nie podzielnym. Dołożyć trzeba jeszcze drugą zmienną sygnalizującą zakończenie wątku. np:

bool zatrzymaj = false;
bool zakonczono = false;

//wątek
while(!zatrzymaj)
{
  //wykonuj obliczenia
}
zakonczono = true;

//program
zatrzymaj = true;
while(!zakonczono) 
#ifdef WINDOWS
  Sleep(10);
#else
  usleep(10);
#endif

Jeśli chodzi o pauzowanie i wznawianie, to można aby pauzować można wątek zatrzymać, aby odpauzować uruchomić go jeszcze raz z aktualnym stanem obliczen. Kwestia odpoiednio zaprojektowanej funkcji liczącej. W przypadku rekurencji można ją zastąpić iteracją + stos.

0

niestety zycie nie zawsze jest takie proste:) jak sam autor powiedzial, nie chodzi mu tylko o zatrzymanie watku, ale takze interakcje jak pauza/wznowienie, odebranie/wyslanie danych itp. synchronizacja moze, ale nie musi sie tu przydac. odczyt/zapis nie zawsze jest atomiczny, wystarczy ze to nie bedzie boolean tylko np. obiekt ze stanem obliczen, itp chore wymysly. przy wielowatkowych na prawde lepiej jest napisac zawczasu z synchronizacja, a optymalizowac ilosc sekcji/semaforow/monitorow pozniej, jak wszystko bedzie zrobione i bedzie poprawne chodzic

ps. wywolywania rekurencyjne mozna pauzowac/wznawiac tak samo prosto jak iteracyjne, bez przerabiania ich na iter+stos

0

Wszystko zależy od tego jak skomplikowane jest zadanie, jak często musimy synchronizować, jak różnorodne dane potrzebujemy wymieniać.
Jak pisałem wcześniej pauzę można zastąpić zakańczaniem i rozpoczynaniem wątku. Wtedy rekurencja odpada bo w momencie kończenia wątku po stosie zostaje wspomnienie ("gdzieś jest, lecz nie wiadomo gdzie" :D ).

ubiquality: napisz dokładniej co robią wątki i jak chcesz aby wyglądała komunikacja, jakie dane i jak często chcesz wymieniać. Wtedy postaramy się dopasować odpowiednią metodę. Synchronizacja bardzo różnie może wyglądać i ściśle zależy od rodzaju wykonywanego zadania.

0

jesli chcesz pauze zastapic na zakanczanie i rozpoczynanie watku, no to coz.. to nie bedzie pauza tylko jej udawanie, defacto tracenie czasu na serializacje/zabicie/utworzenie/deserializacje. o wiele latwiej wprowadzic do funkcji rekurencyjnej (np na jej poczatku) lock mutexa/sekcji krytycznej/monitora/conditionala i natychmiastowy unlock. dla pracy watku oraz reszty systemu taki lock-i-od-razu-unlock jest bez roznicy. natomiast jesli z zewnatrz zostanie zatrzasniety - watek sie dochodzac do niego natychmiast zatrzyma sie, i bedzie zajmowal ~zero czasu procesora. i jest w tym extra bonus: mozesz ustawic ten test w dowolnym miejscu, masz kontrole w ktorym miejscu moze sie zatrzymac, wiec wiesz dokladnie w jakim stanie bedzie watek jak zostanie spauzowany -- i w tym stanie dane np. moga byc przygotowane do odczytu z zewnatrz. i kolejna fajna sprawa - watek mozna bardzo latwo wznowic - owo 'zewnetrzne cos' co zalockowalo mutexa/sekcje/../ robi unlocka i juz watek leci dalej. a jesli to ma byc N watkow - mozna uzyc spinlocka/countedmutex czy jak to tam nazywasz, z liczba N. idealnie sie nada, wystarczy na 'zewnatrz' zmienic lock() na lock(N) i unlock na unlock(N), a kod pojedynczego watku zostaje ten sam. i bedzie pieknie smigac nie marnotrawiac zasobow! a jesli chodzi o zabijanie -- to powyzsze rozwiazanie idealnie da sie polaczyc z takim zabijaniem jak proponowales

0

Witam
Dzięki za odpowiedzi.

Postanowiłem do tego celu użyc klasy wxThread z pakietu wxWidgets. Zauważyłem, że klasa ma gotowe funkcje Pause() oraz Resume(). Doszedłem jednak do wniosku, że w tej klasie, którą piszę teraz, nie będę wykorzystywał tych funkcji, gdyż klasa liczy za pomocą karty graficznej, i nie mam możliwości zapauzowac funkcji wykonywanej w karcie graficznej. To się przyda, gdy będę progrmował drugi wątek dla procesora.
Klasa która dziedziczy z wxThread musi zaimplementowac funkcję virtual void* Entry(), która jest wywoływana jako osobny wątek. Chciałbym na końcu tej funkcji, po wykonaniu obliczeń, poinformowac wątek zewnętrzny o tym. I teraz nie wiem jak. Prubuje wykorzystac do tego celu klase wxCommandEvt, ale konczy się to jak na razie sypaniem się programu :-/ . Może jakieś wskazówki?
A oto kod:

wxCommandEvent event( CGPUEVT_COMPUTATIONS_ENDS, GetId() );
event.SetEventObject( 0 );
m_pFrame->GetEventHandler()->ProcessEvent( event );

m_pFrame to jest wskaznik na klase dziedzicaca z wxFrame, jest to okienko aplikacji.

0

Spróbuj zamiast ProcessEvent użyć AddPendingEvent.

0

dziala:)
spedziłem nad tym pol dnia tylko dlatego, ze wskaznik m_pFrame był ustawiany w głównym procesie tuz po wywolaniu funkcji wxThread::Run() zamiast przed. I wątek nie mial poprawnie zainicjowanego wskaznika. :/
ALe juz to poprawilem i dziala:))
Dzieki wielkie

0
adf88 napisał(a)

Do takich prostych rzeczy jak zatrzymanie wątku nie potrzeba synchronizacji. Wystarczy jedna zmienna mówiąca o tym, czy wątek ma się wykonywać czy nie. Można ją używać bezpiecznie z poziomu każdego wątku, bo odczyt czy zapis jest jednym rozkazem, co za tym idzie nie podzielnym. Dołożyć trzeba jeszcze drugą zmienną sygnalizującą zakończenie wątku. np:

bool zatrzymaj = false;
bool zakonczono = false;

//wątek
while(!zatrzymaj)
{
  //wykonuj obliczenia
}
zakonczono = true;

//program
zatrzymaj = true;
while(!zakonczono) 
#ifdef WINDOWS
  Sleep(10);
#else
  usleep(10);
#endif

Jeśli chodzi o pauzowanie i wznawianie, to można aby pauzować można wątek zatrzymać, aby odpauzować uruchomić go jeszcze raz z aktualnym stanem obliczen. Kwestia odpoiednio zaprojektowanej funkcji liczącej. W przypadku rekurencji można ją zastąpić iteracją + stos.

Przy zastosowaniu tej konstrukcji jesli dodasz jeszcze jeden watek sprawdzajacy np. status poprzez odczyt tych dwoch zmiennych to masz pewny wylot (acces violation) przy kazdej probie zatrzymania/wznowienia watku. Sleep w watku? :-D Eventow zakazali uzywac czy co?

1 użytkowników online, w tym zalogowanych: 0, gości: 1