Wątki pthread.h

0

Witam
piszę aplikację obsługującą kolka wątków na bibliotece pthread.h. Mam utworzoną klasę Drwal oraz zasób drzewaLas, oraz drzewaMagazyn. Chciałbym stworzyć dwa wątki drwala aby scinał drzewa i przenosił do magazynu. Kod wygląda następująco:

class Zasob
{
public:
    Zasob(int ilosc){
        this->ilosc = ilosc;
    }
    ~Zasob(){}

    void dodaj(){
        mut_zasob.lock();
        ilosc++;
        mut_zasob.unlock();
    }
    int zwroc(){
        int tmp;
        mut_zasob.lock();
        tmp = this->ilosc;
        mut_zasob.unlock();
        return tmp;
    }

    void zmniejsz()
    {
        mut_zasob.lock();
        ilosc--;
        mut_zasob.unlock();
    }

private:
    int ilosc;
    mutex mut_zasob;
};


Zasob drzewaLas(1000);
Zasob drzewaMagazynLas(0); 



class Drwal
{
private:
    string coRobi;

public:
    Drwal(){
        this->coRobi = "W spoczynku";
    }




    ~Drwal(){}

    void setCoRobi(string WhatDo){
        this->coRobi = WhatDo;
    }

    string getCoRobi(){
        return this->coRobi;
    }

   void run(){
		
		int losuj;

		while (programDziala){
			losuj = gen() % 1;

			switch (losuj)
	
            {
            case 0:
                //scinaj
                drzewaLas.zmniejsz();
                drzewaMagazynLas.dodaj();

                this->coRobi = "Scina";


            case 1:
                //odpoczywa

                this->coRobi = "PIWKO";


            default:
                break;
            }
        }
    }


};

Moje pytanie brzmi: Jak utworzyć np. dwóch drwali, którzy będą ścianali drzewa?
Mam coś takiego:

int main()
{
        pthread_t D1, D2;
        int d1, d2;
        Drwal d;

        printf("In main: creating thread\n");
        d1 =  pthread_create(&D1, NULL, &Drwal::run, &d);
        if(d1 != 0) {
                printf("Error: pthread_create() failed\n");
                exit(EXIT_FAILURE);
        }

        pthread_exit(NULL);
} 

Lecz sypie mi się w momencie tworzenia wątku D1. Nie wiem jak przekazać funkcję rozpoczęcia wątku :/

1

Nie analizowałem całego kodu, ale nawet jak uruchomisz funkcję, to ona zaraz zostanie zamknięta, bo kończysz program.

0

Spójrz na prototyp

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

który pokazuje, że funkcja wywoływana w nowym wątku powinna mieć z kolei taki prototyp void* start_routine(void *);

czyli wskazywać adres funkcji, metody statycznej lub metody konkretnego obiektu klasy.
0

Hej, ale wiesz, ze masz do dyspozycji takie fajne nagłówki, jak <iostream>, <random> i <thread>?
Tak tylko mowie...

1

Największym problemem jest to, że niepotrzebnie mieszasz oba języki naraz. Staraj się używać tylko standardowych bibliotek języka C++, jak już w nim piszesz. Nagłówek <pthread.h>, bo o nim mowa, dostarcza Ci funkcje napisane z myślą o języku C, dlatego powinieneś użyć nagłówka <thread>. No, ale wracając do meritum:

rudziik napisał(a):

Lecz sypie mi się w momencie tworzenia wątku D1. Nie wiem jak przekazać funkcję rozpoczęcia wątku

zerknij na na nagłówek funkcji tworzącej wątek, której używasz:

pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);

jak widzisz, void *(*)(void *), potrzebujesz przekazać adres do funkcji. Ty natomiast starasz się przekazać adres do zwykłej składowej funkcji klasy Drwal. Żeby móc ją przekazać musisz ją uczynić statyczną (static) i poprawić jej nagłówek na podany wyżej:

static void* run(void* context)

w tej funkcji musisz zastosować rzutowanie context na typ Drwal*, jeśli chcesz się odwoływać do przekazanego obiektu. Twoja funkcja powinna zwracać NULL, a przy caseach brakuje Ci instrukcji break. W warunku pętli while powinieneś sprawdzać, czy zmienna ilosc w obiekcie drzewaLas nie jest mniej niż/równa 0. Więc stwórz sobie funkcję składową w klasie Zasob, np. funkcję pusty, która zwróci Tobie tę informację (wartość logiczną), a warunek popraw na:

while(!drzewaLas.pusty())

i na koniec w funkcji main wywołaj funkcję pthread_join (to bardzo ważne) dla utworzonego wątku D1, by główny wątek czasami się nie zakończył przed jego wykonaniem. Ten sam kod powtórz dla drugiego wątku D2. Mam nadzieję, że dosyć jasno to opisałem.

0

Przypominam o extern "C"...

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