Wątki w c++

0

Jest jakis sprytny pomysl aby przekazac do watku obkiekt klasu albo sam wskaznik do klasy??? (siedzie juz nad tym troche czasu i mam juz powoli dosc).

tworzac watek:
pthread_t tid;
pthread_create(&tid,NULL,funkcja,NULL);

jako 'funkcja' musze podac cos w stylu void*(*)() wiec nie mam pomyslu jakby to ewentualni zrzutowac(o ile sie jakos da) na metode klasy np; MojaKlasa.mojafunkcja() w ktorej bylaby cala obsluga watku z dostepem do skladowych klasy. (bo o to mi glownie chodzi aby watek mial dostep do metod i skladowych klasy)

Jedyne co udalo mi sie zrobic to:

Kopiuj
class MojaKlasa
{
  static void *Thread(void *arg);
}

int main()
{
  MojaKlasa client;
  pthread_t tid; 
  pthread_create(&tid,NULL,client.Thread,NULL);
}

I wszystko byloby cudowanie gdyby funkcja Thread nie byla static, bo przez to nie mam dostepu do niestatycznych skladowych i funkcji klasy...

(Na dzisiaj dosc.. ide spac... :P )

quetzalcoatl
  • Rejestracja:około 18 lat
  • Ostatnio:ponad 6 lat
0
  1. niestety, w tradycyjnym ujeciu posixowym, NIE MOZNA utworzyc watku opierajac sie na metodzie klasy - f.statyczna tak jak masz - moze byc

  2. ostatni parametr w pthread_create to argument dla watku. zwroc uwage ze sygnetura funkcji watku jest void ()(void arg) -- czyli dostaje parametr void*

pomysl o:

Kopiuj
class MojaKlasa
{
    static void Thread(void*arg)
    {
         MojaKlasa* ptr = static_cast<MojaKlasa*>(arg); //ew.dynamic i test czy ok
         ptr->blahblah
    }
}

MojaKlasa client
pthread_create(....., MojaKlasa::Thread, &client);
  1. z uzyciem Boost::thread oraz Boost::bind mozna stworzyc watek z metody klasy, przepraszam za niedokladny przykald, ale mam niewiele czasu
Kopiuj
class MojaKlasa
{
public:
      void Thread()
      { costam }
}

MojaKlasa client;
boost::thread watek(boost::bind(&MojaKlasa::Thread, &client));
//watek juz chodzi!
watek.join(); //czekamy az sie zakonczy

no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
SA
  • Rejestracja:prawie 21 lat
  • Ostatnio:ponad 9 lat
  • Postów:513
0

Innym trikiem jest użycie virtualnych metod bez parametów, wtedy masz dostęp do instancji klasy (this)

Kopiuj
#pragma comment(linker,"/entry:main")
#include "windows.h"

class CBlah
{
	virtual __stdcall Thread1() {MessageBox(0,"thread 1","thread 1",0);}
	virtual __stdcall Thread2() {MessageBox(0,"thread 2","thread 2",0);}
};

int main()
{
	CBlah b;
	DWORD id;
	LPTHREAD_START_ROUTINE *jumptable = *(LPTHREAD_START_ROUTINE**)&b;
	CloseHandle(CreateThread(0, 0, jumptable[0], &b, 0, &id));
	CloseHandle(CreateThread(0, 0, jumptable[1], &b, 0, &id));
	return MessageBox(0,"click me","waiting",0);
}
DX
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 miesiące
  • Postów:1072
0

Jeszcze innym trikiem jest użycie Boost::Threads

Kopiuj
#include <iostream>
#include <boost/thread.hpp>
#include <boost/bind.hpp>


class seeker
{
	boost::mutex m;
	bool finished;
	
	void check()
	{
		{
			boost::mutex::scoped_lock lock(m);
			finished = false;
		}
	
	
		int m_secs(2000);
		boost::xtime xt;
		boost::xtime_get (&xt, boost::TIME_UTC);
		xt.sec += m_secs;
		
		for(int i=0; i < 10; ++i)
		{
			boost::thread::sleep(xt);
			xt.sec += m_secs;
		}
		
		{
			boost::mutex::scoped_lock lock(m);
			finished=true;
		}
	}

	void animate()
	{
		int m_secs(250);
		boost::xtime xt;
		boost::xtime_get (&xt, boost::TIME_UTC);
		xt.sec += m_secs;
		
		while(!finished)
		{
			for(int i=0; i < 3; ++i)
			{
				std::cout << ".";
				boost::thread::sleep(xt);
			}
			std::cout << "\r";
		}
		
		std::cout << "\nFinished" << std::endl;
	}

public:

	seeker(): finished(false) {}

	void seek()
	{
		boost::thread thrd1( boost::bind<void>(boost::mem_fn(&seeker::check), this) );
		thrd1.join(); 
	}
};


int main()
{
	return 0;
}

Najważniejsza jest metoda void seek().

Podsumowując:

  • można

  • przenośne

  • nowoczesne

  • bezpieczne

  • mogą być drobne błędy w tym przykładzie, bo wyciągnięty z głębokich archiwów ;p


Pozdrawia DzieX int getRandomNumber() { return 4; }
quetzalcoatl
  • Rejestracja:około 18 lat
  • Ostatnio:ponad 6 lat
0

dziex - powtarzasz moja odpowiedz

sapero - nie mozesz polegac na tym, ze vtable jest na samym poczatku obiektu, a juz w ogóle-w ogóle ze funkcje w vtable beda w kolejnosci takiej jak ty napisales w kodzie


no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
DX
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 miesiące
  • Postów:1072
0

@quetzalcoatl
Nie do końca, ja pokazałem jak zrobić to wewnątrz metody jakiejś klasy, co jest trochę trudniejsze. Poza tym nie napisałeś zbyt dużo wyjaśnień.

Aha @pawcyk dzięki boost::bind przekażesz dowolną ilośc parametrów do wątku.


Pozdrawia DzieX int getRandomNumber() { return 4; }
quetzalcoatl
  • Rejestracja:około 18 lat
  • Ostatnio:ponad 6 lat
0

DzieX:

do konca, zacytuje sam siebie:

  1. z uzyciem Boost::thread oraz Boost::bind mozna stworzyc watek z metody klasy, przepraszam za niedokladny przykald, ale mam niewiele czasu

boost::thread watek(boost::bind(&MojaKlasa::Thread, &client));
//watek juz chodzi!
watek.join(); //czekamy az sie zakonczy

a teraz Ciebie

boost::thread thrd1( boost::bind<void>(boost::mem_fn(&seeker::check), this) );
thrd1.join();

w dodatku uzyles bind z jawna specyfikacja typu zwracanego (z czym bind by sam sobei poradzil) oraz neipotrzebnie uzyles mem_fn zeby opakowac seeker::check.. masz to samo tylko niepotrzebnie dodatkowo zagmatwane. i w dodatku tez nie napisales zadnych wyjasnien do wielkiego kawala kodu, ktorego 95% nie jest potrzebne zeby powiedziec jak uzyc boost::thread

poza tym - dzieki boost::bind nie przekazesz dowolnej ilosci parametrow. jest ograniczenie o kilkunastu. mozna je sobie powiekszyc np. do 30tu wygenerowujac automatycznie nowe pliki .h dolaczonym w booscie skryptem, ale ograniczenie jest i bedzie zawsze jakies.

poza tym - poprzez pthread tez mozna przekazac dowolna ilosc parametrow - wystarczy je opakowac w structa i przekazac wskaznik na niego, ale to oczywscie jest "na okolo".


no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
DX
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 miesiące
  • Postów:1072
0
dziex napisał(a)
  • mogą być drobne błędy w tym przykładzie, bo wyciągnięty z głębokich archiwów ;p

Ja też zacytuję.

quetzalcoatl napisał(a)

poza tym - dzieki boost::bind nie przekazesz dowolnej ilosci parametrow. jest ograniczenie o kilkunastu. mozna je sobie powiekszyc np. do 30tu wygenerowujac automatycznie nowe pliki .h dolaczonym w booscie skryptem, ale ograniczenie jest i bedzie zawsze jakies.

Żaden normalny programista nie wykorzysta nawet kilkunastu.

quetzalcoatl napisał(a)

poza tym - poprzez pthread tez mozna przekazac dowolna ilosc parametrow - wystarczy je opakowac w structa i przekazac wskaznik na niego, ale to oczywscie jest "na okolo".

A co jeśli masz do czynienia z funkcją biblioteczną która przyjmuje konkretne parametry a nie wskaźnik do struktury? Oczywiście można napisać sobie dodatkową funkcję która to zrobi, a którą z kolei my przekażemy do wątku. I tak dalej... Ogólnie nie lubie pisać czegoś co już dawno zostało napisane.

Aha, dochodzi jeszcze rzutowanie void*.

quetzalcoatl napisał(a)

w dodatku uzyles bind z jawna specyfikacja typu zwracanego (z czym bind by sam sobei poradzil) oraz neipotrzebnie uzyles mem_fn zeby opakowac seeker::check.. masz to samo tylko niepotrzebnie dodatkowo zagmatwane. i w dodatku tez nie napisales zadnych wyjasnien do wielkiego kawala kodu, ktorego 95% nie jest potrzebne zeby powiedziec jak uzyc boost::thread

Jawna specyfikacja zapisu to żaden błąd, wręcz poprawia czytelność kodu (o ile ktoś wie o co chodzi). mem_fn pojawiła się w tym kodzie przypadkowo - eksperymentowałem trochę.


Pozdrawia DzieX int getRandomNumber() { return 4; }
SA
  • Rejestracja:prawie 21 lat
  • Ostatnio:ponad 9 lat
  • Postów:513
0

quetzalcoatl, nie wprowadzaj ludzi w błąd takimi posłyszeniami.
Vtable zawsze jest jako pierwsza zmienna klasy, a kolejność adresów w niej też odpowiada kolejności w kodzie. Gdyby tak nie było to używanie np. MFC byłoby niebezpieczne, ba, windows nie miałby prawa działać bo opiera się na takich właśnie klasach.
Taki jest standard i nikt tego nie podważy.

quetzalcoatl
  • Rejestracja:około 18 lat
  • Ostatnio:ponad 6 lat
0

sapero - to jest zdefiniwane w standardzie c++? nie pamietam.. wydawalo mi sie ze to jest platform-specific i windowsy moga sobie miec jeden uklad, linux inny, a mac z kosmosu.. w takim razie bije sie w piersi i przepraszam

dziex - alez calkowicie sie zgadzam, ogolnie to chcialem tylko powiedziec ze juz o boost::thread/boost::bind pisalem i ze sprowadza sie w zasadzie tylko do 2 prostych linijek.. wyznaje zasade ze im zwiezlejszy przyklad tym lepiej bedzie zrozumiany. a przyczepilem sie do stwierdzenia "bind - dowolna" , poniewaz <ort>w ogóle </ort>jest jakies ograniczenie w ilosci bezposrednich parametrow dla boost::bind (i dla boost::lambda::bind tez!) i przez to nie udaje czasem sie zbindowac na przyklad jakies funkcji z WINAPI - i sam wiesz ile potrafia miec parametrow i jak czytelne sa komunikaty o bledach z bind.. ja stracilem kiedys 3 godziny na szykaniu bledu, zanim przypadkiem natrafilem na #define informuajcy o wysokosci ograniczenia..


no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
DX
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 miesiące
  • Postów:1072
0

@quetzalcoatl

Fakt, sory za wprowadzanie w błąd.


Pozdrawia DzieX int getRandomNumber() { return 4; }
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)