C++ pthreads zadanie na wątki

C++ pthreads zadanie na wątki
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0

Cześć,
Mam mały problem, aczkolwiek chce napisać program z wykorzystaniem wątków i biblioteki pthreads.
Szczegół w tym, że wymyśliłem sobie takie zadanie:
"Mamy 10 profesorów i niekończącą się liczbę studentów, każdy student musi odwiedzić czterech różnych prowadzących by zebrać od nich wpis do indexu, maxymalnie może chodzić 10 studentów i jak liczba ich się zmniejsza to na miejsce tego, który zebrał już wpis wskakuje nowy. Oczywistym jest, ze u jednego profesora aktualnie może być jeden student odbierający wpis. Jeżeli student natrafi na zajętego profesora to idzie do kolejnego by nie czekać a jak już musi czekać to czeka aż się zwolni."

Moim problemem jest to, że wymyśliłem sobie zadanie próbuję się za nie zabrać od godziny 16 (dnia 06.01) i nie wiem jak mam to zrobić.

Nie widzę odwzorowania w wątkach...
Student czy profesor jest wątkiem ? raz tak mi pasuje a raz tak. a najlepiej by było jak by byli nim obaj... tylko jak w tedy mieć nie ograniczoną liczbę studentów ?

na chwilę obecną mam coś takiego:

Kopiuj
#include <iostream>
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
extern "C"
 {
    #include <pthread.h>
 }

using namespace std;

struct index //deklaracja struktury
{
   double przedmiot1;
   double przedmiot2;
   double przedmiot3;
   double przedmiot4;
};

pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;

void * Student(void * arg);
void * Profesor(void * arg);

int b;  /* buffer size = 1; */
int turn=0;

int  st_online = 0; //ilosc studentow zbierajacych wpisy

int main()
{
   srand (time(NULL));
   pthread_t student_1,student_2,student_3,student_4,student_5,student_6,student_7,student_8,student_9;

   index notes=
   {
	   1,
	   3,
	   4,
	   1
   };
   //Tworzenie watkow studentow (ktorzy bd zbierac pisy)
   pthread_create( &student_1, NULL, &Student, &notes);
   pthread_create( &student_2, NULL, &Student, &notes);
   pthread_create( &student_3, NULL, &Student, &notes);
   pthread_create( &student_4, NULL, &Student, &notes);
   pthread_create( &student_5, NULL, &Student, &notes);
   pthread_create( &student_6, NULL, &Student, &notes);
   pthread_create( &student_7, NULL, &Student, &notes);
   pthread_create( &student_8, NULL, &Student, &notes);
   pthread_create( &student_9, NULL, &Student, &notes);

   pthread_join( student_1, NULL);


   cout << "Koniec Programu " << endl;
   return 0;
}
void add_buffer(int i){
  st_online = i;
}
int get_buffer(){
  return st_online ;
}
void Profesor(index &a)
{
	a=
	{
		(rand() % 6 + 2),
		(rand() % 6 + 2),
		(rand() % 6 + 2),
		(rand() % 6 + 2)
	}; cout <<"Profesor mode";
}

void *Student(void * arg)
{
	add_buffer(1);
	index notes_studenta;
	notes_studenta=*((index*)arg);
	pthread_mutex_lock( &count_mutex );
	Profesor(notes_studenta);
	//pthread_mutex_lock( &count_mutex );
	//pthread_mutex_unlock( &count_mutex );
	cout <<"I'm a student\n";
	cout << notes_studenta.przedmiot1 << endl;
	pthread_mutex_unlock( &count_mutex );
	pthread_exit(NULL);
}
 

Jakieś pomysły jakieś rady ?
co kol wiek... Jak wy to widzicie kto jest wątkiem a kto czym ?
Jak to odwzorować w wątkach ?

HO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 11 lat
  • Postów:283
0

Na mój gust profesor to wątek. Każdy profesor ma zbiór studentów do niego uczęszczających, zbiór jest uzupełniany gdy wypisany jest student. Student jest blokowany(dane) gdy profesor go magluje.

Natomiast ta część zadania mi się nie podoba.

Oczywistym jest, ze u jednego profesora aktualnie może być jeden student odbierający wpis. Jeżeli student natrafi na zajętego profesora to idzie do kolejnego by nie czekać a jak już musi czekać to czeka aż się zwolni.

Kiedy np. ustawi się pełna kolejka 10 studentów do jednego profesora? Powinno to się rozkładać równomiernie a wygląda tak, że jeśli każdy profesor jest zajęty to ten co przyszedł czeka w kolejce u ostatniego - tak to rozumiem, ale mogę źle pojmować bo późna pora. Przez to szybko może zrobić się kolejka 10 u ostatniego profesora a na pozostałych pustka.


Jeśli uważasz mój post za wartościowy - daj punkt.
Mój post pomógł Ci rozwiązać problem - zaznacz go. Pozdrawiam
SH
ale student ma do zebrania 4 oceny, u czterech różnych profesorów. Jak jest jeden zajęty a ma nie zebrane inne to nie czeka tylko zbiera inne. a jezeli ma reszte zebrane to czeka. Tak mi się wydaje :P wymyśliłem to zadanie 2 tygodnie temu teraz postanowiłem się za nie zabrać i przyznam nie wiem za bardzo jak ;d
HO
Student reprezentuje dane, profesor te dane wypełnia - jest wątkiem - tak to wygląda z mojego punktu widzenia.
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0

załóżmy, że prowadzący jest wątkiem
Tak więc mamy 10 wątków, które oceniają studentów.
każdy student odwiedza 10 prowadzących
-ale kim jest student funkcją ?
-strukturą ?
Jak dodawać nowych studentów ?

HO
Student to klasa - w uproszczeniu może mieć pola dotyczące ocen. Nowych studentów uzyskujesz z generatora. Podobne zadanie na wątki dotyczy np. dostawców, producentów i klientów - myślę że jak poszukasz to napotkasz na tego typu zadanie, trochę podobne do Twojego.
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0
Kopiuj
 
/*
*Shial
*g++ -Wall -lpthread -o threads.exe thread.cpp
*
*/

#include <iostream>
extern "C"
 {
    #include <pthread.h>
	#include <semaphore.h>
	#include <unistd.h>
 }

using namespace std;


struct Index
{
	int pierwsza,druga,trzecia,czwarta;
};
struct Param
{
	int id;
};

pthread_mutex_t mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;

sem_t wolny, zajety;

void * Student(void * arg);
void * Profesor(void * arg);

pthread_t *studentTab=NULL;
pthread_t *profesorTab=NULL;

int main()
{
	Param param;
	
	//ustawiamy atrybuty na domyslna wartosc
	pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_mutex_init(&mutex, NULL);
    sem_init(&wolny, 0, 0);
    sem_init(&zajety, 0, 0);
	cout<<"inicjalizujemy watki\n";
	//inicjalizujemy 10 watkow studentow
	studentTab=new pthread_t[10];
	profesorTab=new pthread_t[10];
	for(int i=0; i<10; i++)
	{
		pthread_create( &studentTab[i], NULL, &Student, NULL);
		param.id=i;
		pthread_create( &profesorTab[i], NULL, &Profesor, &param);
	}
	cout<<"Rozpoczynamy dzialanie watkow\n";
	//Rozpoczynamy dzialanie watkow
	for(int i=0; i<10; i++)
	{
		//pthread_join( profesorTab[i], NULL);
		//pthread_join( studentTab[i], NULL);
	}
	
    pthread_attr_destroy(&attr);
	pthread_mutex_destroy(&mutex);
    sem_destroy(&wolny);
    sem_destroy(&zajety);
	delete [] studentTab;
	delete [] profesorTab;
    pthread_exit(NULL);
	cout << "Koniec Programu " << endl;
	return 0;
}


/*
 * Kod Profesora.
 *
 * Jezeli nie masz studenta u siebie poczekaj az jakis przyjdzie
 * Zarzadaj dostepu do indexu studenta
 * Wpisz ocene studentowi do indexu
 * Zwolnij index studenta.
 * Poinformuj, ze index studenta jest wolny
 */
void *Profesor(void * arg)
{
	int id=0;
    id = (*(Param*)(arg)).id;
	cout <<"Startuje Profesor: "<<id<<endl;
	while (1) 
	{
        sem_wait(&zajety);
        pthread_mutex_lock(&mutex);
		//Czynnosci wykonywane na indexie
		cout <<"Profesor: "<<id<<endl;
		sleep(1);
        pthread_mutex_unlock(&mutex);
        sem_post(&wolny);
    }
}
/*
 * Kod Studenta.
 *
 * Jezeli index jest u profesora poczekaj az sie zwoli.
 * Zarzadaj dostepu do swojego indexu
 * idz do innego prowadzacego.
 * Zwolnij index.
 * Poinformuj, ze dajesz index do oceny
 */
void *Student(void * arg)
{
	Index index_s;
	index_s=
	{
		0,0,0,0
	};
	cout <<"Startuje Student: "<<endl;
	while (1) 
	{
        sem_wait(&wolny);
        pthread_mutex_lock(&mutex);
		//Czynnosci wykonywane w poszukiwaniu profesora
		cout <<"Student: "<<endl;
		sleep(1);
        pthread_mutex_unlock(&mutex);
        sem_post(&zajety);
    }
}

Napisałem taki kod. Dodałem Komentarze tak by był łatwy do ogarnięcia
Teraz nasuwa się pytanie co z indexem ?
Jak obsłużyć index studentów ?
Jak student ma wybierać prowadzącego ? jak prowadzący ma umieszczać ocenę w indexie studenta ?

edytowany 1x, ostatnio: Shial
Zobacz pozostałe 2 komentarze
ZN
Po co dodaje się extern &quot;C&quot; przy dołączaniu nagłówków?
SH
@znaczek dodaje się po to by był rozpoznawany przez C++i daje informację kompilatorowi, że ma być kompilowany tak samo jak w C
SH
oczywiście mowa o bibliotekach zawartych w tym module
Azarien
nagłówki powinny mieć w sobie już extern &quot;C&quot; pod odpowiednim ifdefem. czyżby te nie miały?
SH
Ja korzystam z CygWin by pisac pod linux'a :s i w nim bez tego mi po prostu nie przechodzi ale pod czystym linuxem mi przechodzi
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
1

Profesor - to wątek.
Student - to rekord w jednej z 3-ch kolejek.

Jest 3 kolejki dla studentów którzy mają 1 podpis, 2 podpisy, 3 podpisy.

Profesor przeszukuje kolejki w kolejności 3,2,1 w poszukiwaniu studenta który potrzebuje jego podpisu.
Jeżeli znajduje to wyciąga go z tej kolejki, dodaje swój podpis, wrzuca do kolejnej (o ile nie wyciągnął z 3-ciej)
Jeżeli nie znajduje to tworzy sobie studenta, dodaje podpis, wrzuca do kolejki 1.

Można tez dodać kolejki 0 i 4 wtedy profesor nigdy nie usuwa studenta i nigdy nie tworzy, ale w takim razie:

  • jeżeli profesor nic nie znalazł to zaczyna szukanie od początku (może po przerwie 1ms)
  • dodatkowy wątek który będzie zajmował się wywaleniem studentów z kolejki 4 oraz pilnowaniem aby w kolejce 0 było co najmniej 1 student (ale lepiej 10).

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 2x, ostatnio: _13th_Dragon
SH
Dzięki za pomysł, zaraz to zaimplementuję i pokażę rezultat. Kolejka fifo będzie idealna myślę...
SH
w poście poniżej zamieszczam kod, tak sobie to wyobrażałeś ?
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0
Kopiuj
/*
*shial
*g++ -Wall -lpthread -o threads.exe thread.cpp
*/

#include <iostream>
#include <deque>
#include <stdlib.h>
#include <time.h>
extern "C"
 {
    #include <pthread.h>
	#include <semaphore.h>
	#include <unistd.h>
 }

using namespace std;

/*srand (time(NULL));
 * Kod Studenta.
 *
 * Student jest rekordem
 * Posiadajacym dwie tablice
 * Tablice profesorow od ktorych ma odebrac wpis
 * Tablcie reprezentujaca index
 */
struct StudentRekord
{
	int Profesor[4];
	int Index[4];
};

//Parametr Profesora, reprezentujący jego index w tablicy
struct Param
{
	int id;
};

deque < StudentRekord > kolejka0;
deque < StudentRekord > kolejka1;
deque < StudentRekord > kolejka2;
deque < StudentRekord > kolejka3;
deque < StudentRekord > kolejka4;

pthread_mutex_t mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;

sem_t wolny, zajety;

void * Profesor(void * arg);

StudentRekord UtworzStudenta()
{
	StudentRekord student;
	for(int i=0;i<4;i++)
		student.Profesor[i]= rand()%11;
	for(int j=0;j<4;j++)
		student.Index[j]=0;
	return student;
}

pthread_t *profesorTab=NULL;

int main()
{
	srand (time(NULL));
	Param param;
	
	//ustawiamy atrybuty na domyslna wartosc
	pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_mutex_init(&mutex, NULL);
    sem_init(&wolny, 0, 0);
    sem_init(&zajety, 0, 0);
	cout<<"inicjalizujemy watki\n";
	//inicjalizujemy 10 watkow studentow
	profesorTab=new pthread_t[10];
	for(int i=0; i<10; i++)
	{
		param.id=i;
		cout <<"nasze i: "<<i<<endl;
		pthread_create( &profesorTab[i], NULL, &Profesor, &param);
	}
	cout<<"Rozpoczynamy dzialanie watkow\n";
	//Rozpoczynamy dzialanie watkow
	for(int i=0; i<10; i++)
	{
		pthread_join( profesorTab[i], NULL);
	}
	
    pthread_attr_destroy(&attr);
	pthread_mutex_destroy(&mutex);
    sem_destroy(&wolny);
    sem_destroy(&zajety);
	delete [] profesorTab;
    pthread_exit(NULL);
	cout << "Koniec Programu " << endl;
	return 0;
}

/*
 * Kod Profesora.
 *
 * Profesor przeszukuje kolejki w kolejności 3,2,1 
 * w poszukiwaniu studenta który potrzebuje jego podpisu.
 * Jeżeli znajduje to wyciąga go z tej kolejki, dodaje swój podpis, wrzuca do kolejnej (o ile nie wyciągnął z 3-ciej)
 * Jezeli kazda kolejka jest pusta to tworzy studenta i pwrzuca go do kolejki zerowej
 */
void *Profesor(void * arg)
{
	int id=0;
    id = (*(Param*)(arg)).id;
	unsigned sz;
	cout <<"Startuje Profesor: "<<id<<endl;
	while (1) 
	{
        //sem_wait(&zajety);
        pthread_mutex_lock(&mutex);
		if( kolejka1.empty()&&kolejka2.empty()&&kolejka3.empty()&&kolejka0.empty())
			kolejka0.push_back(UtworzStudenta());
		// Sprawdzenie kolejki ze studentami, ktorzy maja juz trzy wpisy
		sz= kolejka3.size();
		if(!kolejka3.empty());
			for (unsigned j=0; j<sz; j++)
				for(int i=0;i<4;i++)
					if(kolejka3[j].Profesor[i]==id)
					{
						kolejka3[j].Index[i]=rand()%5+2;
						kolejka4.push_back(kolejka3[j]);
						kolejka3.erase(kolejka3.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
		// Sprawdzenie kolejki ze studentami, ktorzy maja dwa wpisy
		sz= kolejka2.size();
		if(!kolejka2.empty());
			for (unsigned j=0; j<sz; j++)
				for(int i=0;i<4;i++)
					if(kolejka2[j].Profesor[i]==id)
					{
						kolejka2[j].Index[i]=rand()%5+2;
						kolejka3.push_back(kolejka3[j]);
						kolejka2.erase(kolejka2.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
		// Sprawdzenie kolejki ze studentami, ktorzy maja jeden wpisy
		sz= kolejka1.size();
		if(!kolejka1.empty());
			for (unsigned j=0; j<sz; j++)
				for(int i=0;i<4;i++)
					if(kolejka1[j].Profesor[i]==id)
					{
						kolejka1[j].Index[i]=rand()%5+2;
						kolejka2.push_back(kolejka3[j]);
						kolejka1.erase(kolejka1.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
		// Sprawdzenie kolejki ze studentami, ktorzy ne maja jeszcze wpisu
		sz= kolejka0.size();
		if(!kolejka0.empty());
			for (unsigned j=0; j<sz; j++)
				for(int i=0;i<4;i++)
					if(kolejka0[j].Profesor[i]==id)
					{
						kolejka0[j].Index[i]=rand()%5+2;
						kolejka1.push_back(kolejka3[j]);
						kolejka0.erase(kolejka0.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
						
        pthread_mutex_unlock(&mutex);
		sleep(1000);
        //sem_post(&wolny);
    }
}

 

to najaktualniejszy kod jaki zrobiłem. Ale mamy mały problem ponieważ wątki mi się wygładzają czy jak tam mówią mamy death lock'a.
Błędu jeszcze nie znalazłem.
Pytanie do kolegi wyżej czy tak to sobie wyobrażał?

SH
musiałem przeładować bo było moje imię i nazwisko ;d
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
1
  1. nie potrzebujesz kolejki 0 ani 4
  2. każda kolejka musi mieć swój mutex
  3. dodatkowy mutex na wyświetlenie informacji

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
SH
mutex(nie wiem czy dobrze je stosuję) on ma zablokowywać dane przed dostępem innych wątków tak ? tak jak na dole, dobrze to zrobiłem ?
SH
a pytanie inaczej, to mutex w mutexie jeszcze trzeba tam gdzie wykorzystuję kolejkę np trzecią przy kolejce drugiej right ?
_13th_Dragon
Kolejki nie wykorzystują siebie nawzajem, najpierw s jednej się usuwa potem do drugiej się dodaje.
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0
Kopiuj
/*
*shial
*g++ -Wall -lpthread -o threads.exe thread.cpp
*/

#include <iostream>
#include <deque>
#include <stdlib.h>
#include <time.h>
extern "C"
 {
    #include <pthread.h>
	#include <semaphore.h>
	#include <unistd.h>
 }

using namespace std;

/*srand (time(NULL));
 * Kod Studenta.
 *
 * Student jest rekordem
 * Posiadajacym dwie tablice
 * Tablice profesorow od ktorych ma odebrac wpis
 * Tablcie reprezentujaca index
 */
struct StudentRekord
{
	int Profesor[4];
	int Index[4];
};

//Parametr Profesora, reprezentujący jego index w tablicy
struct Param
{
	int id;
};

deque < StudentRekord > kolejka0;
deque < StudentRekord > kolejka1;
deque < StudentRekord > kolejka2;
deque < StudentRekord > kolejka3;

pthread_mutex_t mutex0     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex1     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3     = PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;


void * Profesor(void * arg);
void * Portier(void * arg);

StudentRekord UtworzStudenta()
{
	StudentRekord student;
	for(int i=0;i<4;i++)
		student.Profesor[i]= rand()%10;// random number from 0 to 9
	for(int j=0;j<4;j++)
		student.Index[j]=0;
	return student;
}

pthread_t *profesorTab=NULL;
pthread_t portier;
int main()
{
	srand (time(NULL));
	Param param;
	
	//ustawiamy atrybuty na domyslna wartosc
	pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_mutex_init(&mutex0, NULL);
	pthread_mutex_init(&mutex1, NULL);
	pthread_mutex_init(&mutex2, NULL);
	pthread_mutex_init(&mutex3, NULL);

	cout<<"inicjalizujemy watki\n";

	pthread_create( &portier, NULL, &Portier, NULL);
	//inicjalizujemy 10 watkow studentow
	profesorTab=new pthread_t[10];
	for(int i=0; i<10; i++)
	{
		param.id=i;
		cout <<"nasze i: "<<i<<endl;
		pthread_create( &profesorTab[i], NULL, &Profesor, &param);
	}
	cout<<"Rozpoczynamy dzialanie watkow\n";
	//Rozpoczynamy dzialanie watkow
	pthread_join( portier, NULL);
	for(int i=0; i<10; i++)
	{
		pthread_join( profesorTab[i], NULL);
	}
	
    pthread_attr_destroy(&attr);
	pthread_mutex_destroy(&mutex0);
	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);
	pthread_mutex_destroy(&mutex3);
	delete [] profesorTab;
    pthread_exit(NULL);
	cout << "Koniec Programu " << endl;
	return 0;
}

/*
 * Kod Profesora.
 *
 * Profesor przeszukuje kolejki w kolejności 3,2,1 
 * w poszukiwaniu studenta który potrzebuje jego podpisu.
 * Jeżeli znajduje to wyciąga go z tej kolejki, dodaje swój podpis, wrzuca do kolejnej (o ile nie wyciągnął z 3-ciej)
 * Jezeli kazda kolejka jest pusta to tworzy studenta i pwrzuca go do kolejki zerowej
 */
void *Profesor(void * arg)
{
	int id=0;
    id = (*(Param*)(arg)).id;
	unsigned sz;
	cout <<"Startuje Profesor: "<<id<<" <-> "<<endl;
	while (1) 
	{
		pthread_mutex_lock(&mutex3);
		// Sprawdzenie kolejki ze studentami, ktorzy maja juz trzy wpisy
		sz= kolejka3.size();
		if(!kolejka3.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke3"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka3[j].Profesor[i]==id)
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka3)"<<endl;
						kolejka3[j].Index[i]=rand()%5+2;
						kolejka3.erase(kolejka3.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
				}
			}
		}
		pthread_mutex_unlock(&mutex3);
		sleep(1);
		pthread_mutex_lock(&mutex2);
		// Sprawdzenie kolejki ze studentami, ktorzy maja dwa wpisy
		sz= kolejka2.size();
		if(!kolejka2.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke2"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka2[j].Profesor[i]==id)
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka2)"<<endl;
						kolejka2[j].Index[i]=rand()%5+2;
						pthread_mutex_lock(&mutex3);
						kolejka3.push_back(kolejka2[j]);
						pthread_mutex_unlock(&mutex3);
						kolejka2.erase(kolejka2.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
				}
			}
		}
		pthread_mutex_unlock(&mutex2);
		sleep(1);
		pthread_mutex_lock(&mutex1);
		// Sprawdzenie kolejki ze studentami, ktorzy maja jeden wpisy
		sz= kolejka1.size();
		if(!kolejka1.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke1"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka1[j].Profesor[i]==id)
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka1)"<<endl;
						kolejka1[j].Index[i]=rand()%5+2;
						pthread_mutex_lock(&mutex2);
						kolejka2.push_back(kolejka1[j]);
						pthread_mutex_unlock(&mutex2);
						kolejka1.erase(kolejka1.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}	
				}
			}
		}
        pthread_mutex_unlock(&mutex1);
		sleep(1);
		pthread_mutex_lock(&mutex0);
		// Sprawdzenie kolejki ze studentami, ktorzy nie maja wpisow
		sz= kolejka0.size();
		if(!kolejka0.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke0"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka0[j].Profesor[i]==id)
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka1)"<<endl;
						kolejka0[j].Index[i]=rand()%5+2;
						pthread_mutex_lock(&mutex1);
						kolejka1.push_back(kolejka0[j]);
						pthread_mutex_unlock(&mutex1);
						kolejka0.erase(kolejka0.begin()+j);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}	
				}
			}
		}
        pthread_mutex_unlock(&mutex0);
		sleep(1);
    }
}
/*
 * Kod Portiera.
 *
 * Utrzymuje kolejke zerowa by bylo w niej przynajmnie 10 studentów
 * Jezeli jest mniej niz 10 studentow dorabia 10 nowych
 */
void *Portier(void * arg)
{
	cout <<"Portier zaczal swoja prace"<<endl;
	pthread_mutex_lock(&mutex0);
		if(kolejka0.size()<10)
		{
			StudentRekord abc;
			for(int i=0;i<10;i++)
			{
				abc=UtworzStudenta();
				kolejka1.push_back(abc);
			}cout <<"Portier utworzyl nowych studentow"<<endl;
		}
	pthread_mutex_unlock(&mutex0);
	sleep(2);
}

wygląda tak kod. Dałem sleep po kazdym mutexie ale dalej nie wiem gdzie jest black-point
@Edit na prawdę nie za bardzo kminię dlaczego zawieszają się po starcie 9 wątku
@Edit2 poprawiłem coś dodałem mutexy tam gdzie ich brakowało jeszcze tak mi się wydaje, ale nadal nie działa nie ruszają
@Edit3 kod cały czas aktualizuje tutaj
@Edit4 Znalazłem błąd, który poprawiłem ale i tak nie rozwiązał sprawy... wątki ruszają się teraz kroczek dalej tylko :p
kod uaktualniony-> błędem było, że jak listy były puste do tworząc nowych studentów nie dodawałem ich do listy

edytowany 6x, ostatnio: Shial
SH
co jest źle ? dlaczego nie działa ?
SH
Praca kończy się na tym, ze zostają dodane wpisy i nic więcej (pierwsze 10 wpisów do listy od jednego profesora)
SH
działa i nagle wywala "segmentation foult" ;/
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
1
Kopiuj
                pthread_create( &profesorTab[i], NULL, &Profesor, &i);
...
void *Profesor(void * arg)
{
        int id=*(int*)arg;
Kopiuj
struct StudentRekord
{
        int Profesor32;
...
 if(kolejka1[j].Profesor32&(1<<id)) // jeżeli brak podpisu
...
kolejka1[j].Profesor32&=~(1<<id); // dodaj podpis

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
Zobacz pozostałe 12 komentarzy
_13th_Dragon
Wszystkie operacje na kolejce muszą być "pod" putex'em. Operacje bitowy znacznie uproszczają kod. Miałem nadzieje że sam zauważysz że erase też musi być pod mutex'em.
SH
jeszcze jedno. <code=cpp>if(kolejka1[j].Profesor32&(1<<id)) // jeżeli brak podpisu</code> bo to jest dla jednego ja i tak sobie to z tablica porównuję bitowo <code=cpp>if(kolejka1[j].Profesor32[i]&(1<<id)) // jeżeli brak podpisu</code> to masz na myśli tak ?
_13th_Dragon
nie, wszystkie podpisy ulokowane w jednej liczbie.
SH
i ja tego nie rozumiem ;d
_13th_Dragon
to obejrzyj kod niżej, dodaje 4 losowe liczby, pokazuje co dodano, po jednej usuwa.
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0

w tym fragmencie jeszcze coś mogę powiedzieć, przesunięcie bitowe względem id naszego profesora następnie AND a;le co nam ma to dać ?

Kopiuj
 Profesor32&(1<<id))

a tej lini

Kopiuj
 kolejka1[j].Profesor32&=~(1<<id); // dodaj podpis

to ja już nie ogarniam. Co to robi ?

edytowany 1x, ostatnio: Shial
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
0
Kopiuj
unsigned p32=0;
for(unsigned i=0;i<4;++i) p32|=(1<<(rand()%32)); // dodajemy losowe liczby;
for(unsigned i=0;i<32;++i) if(p32&(1<<i)) cout<<"dodana liczba "<<i<<endl;
for(unsigned i=0;i<32;++i) if(p32&(1<<i)) p32&=~(1<<i); // usuwamy te liczby
cout<<pr32<<endl; // powiino być 0

Albo tak:

Kopiuj
unsigned p32=0; // nic nie ma
for(unsigned i=0;i<4;++i) p32|=(1<<(rand()%32)); // dodajemy losowe liczby;
while(p32)
  {
   for(unsigned i=0;i<32;++i)
     {
      if(p32&(1<<i)) // widze liczbe
        {
         cout<<"widze liczbe "<<i<<endl;
         p32&=~(1<<i); // usuwam liczbe
        }
     }
  }

http://ideone.com/DXFyfw


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 4x, ostatnio: _13th_Dragon
Zobacz pozostałe 8 komentarzy
SH
w takim razie ja nie potrzebuję struktury, po prostu rozlosuje profesorów a potem ich bd czyścił po kolei
_13th_Dragon
Dokładnie tak o ile poprawnie rozumiesz zadanie. Wg mnie w zadaniu mowa o tym że student ma odwiedzić dowolnych 4-ch (a nie z góry wylosowanych 4-ch) - wtedy na odwrót zahaczasz profesorów.
SH
dodałem nową wersję kodu. dopiero jak napisałeś, ze nie potrzebuję indexu i ocen to zrozumiałem Twoją wizję na ten temat(tak mi się wydaje, ze ją zrozumiałem) pozostaje jeszcze temat mutexu :p
_13th_Dragon
to proste wszystkie operacje nad kolejką wyszukiwanie, wstawianie, usuwanie - w ramach odpowiadającej tej kolejce mutex'u. Oraz co najważniejsze wszelkie informacje drukowane cout'em na ekran w ramach dodatkowego mutex'u
SH
Ok. dodaje, dzięki za wskazówkę co do iostreama
SH
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 6 lat
  • Postów:69
0

Kod z zastosowana Twoją inwencją twórczą wygląda tak:
Powiem, ze sprytne rozwiązanie :) podoba mi się.
Ale dalej mam

segmentation fault

Kopiuj
/*
*shial
*g++ -Wall -lpthread -o threads.exe thread.cpp
*/

#include <iostream>
#include <deque>
#include <stdlib.h>
#include <time.h>
extern "C"
 {
    #include <pthread.h>
	#include <semaphore.h>
	#include <unistd.h>
 }

using namespace std;

/*srand (time(NULL));
 * Kod Studenta.
 *
 * Student jest rekordem
 * Posiadajacym dwie tablice
 * Tablice profesorow od ktorych ma odebrac wpis
 * Tablcie reprezentujaca index
 */
int UtworzStudenta()
{
	int StudentRekord=0;
	for(int i=0;i<4;i++)
		StudentRekord|=(1<<(rand()%10)); // dodajemy losowe liczby;
	return StudentRekord;
}


deque < int > kolejka0;
deque < int > kolejka1;
deque < int > kolejka2;
deque < int > kolejka3;

pthread_mutex_t mutex_erase     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex0     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex1     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3     = PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t space_available = PTHREAD_COND_INITIALIZER;


void * Profesor(void * arg);
void * Portier(void * arg);

pthread_t *profesorTab=NULL;
pthread_t portier;
int main()
{
	srand (time(NULL));
	//ustawiamy atrybuty na domyslna wartosc
	pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	pthread_mutex_init(&mutex_erase, NULL);
    pthread_mutex_init(&mutex0, NULL);
	pthread_mutex_init(&mutex1, NULL);
	pthread_mutex_init(&mutex2, NULL);
	pthread_mutex_init(&mutex3, NULL);

	cout<<"inicjalizujemy watki\n";

	pthread_create( &portier, NULL, &Portier, NULL);
	//inicjalizujemy 10 watkow studentow
	profesorTab=new pthread_t[10];
	for(int i=0; i<10; i++)
	{
		cout <<"nasze i: "<<i<<endl;//Parametr Profesora, reprezentujący jego index w tablicy
		pthread_create( &profesorTab[i], NULL, &Profesor, &i);
	}
	cout<<"Rozpoczynamy dzialanie watkow\n";
	//Rozpoczynamy dzialanie watkow
	pthread_join( portier, NULL);
	for(int i=0; i<10; i++)
	{
		pthread_join( profesorTab[i], NULL);
	}
	
    pthread_attr_destroy(&attr);
	pthread_mutex_destroy(&mutex_erase);
	pthread_mutex_destroy(&mutex0);
	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);
	pthread_mutex_destroy(&mutex3);
	delete [] profesorTab;
    pthread_exit(NULL);
	cout << "Koniec Programu " << endl;
	return 0;
}

/*
 * Kod Profesora.
 *
 * Profesor przeszukuje kolejki w kolejności 3,2,1 
 * w poszukiwaniu studenta który potrzebuje jego podpisu.
 * Jeżeli znajduje to wyciąga go z tej kolejki, dodaje swój podpis, wrzuca do kolejnej (o ile nie wyciągnął z 3-ciej)
 * Jezeli kazda kolejka jest pusta to tworzy studenta i pwrzuca go do kolejki zerowej
 */
void *Profesor(void * arg)
{
	int id=0;
    id=*(int*)arg;
	unsigned sz;
	cout <<"Startuje Profesor: "<<id<<" <-> "<<endl;
	while (1) 
	{
		pthread_mutex_lock(&mutex3);
		// Sprawdzenie kolejki ze studentami, ktorzy maja juz trzy wpisy
		sz= kolejka3.size();
		if(!kolejka3.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke3"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka3[j]&(1<<id))
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka3)"<<endl;
						kolejka3[j]&=~(1<<id); // odznaczamy profesora
						pthread_mutex_lock(&mutex_erase);
						kolejka3.erase(kolejka2.begin()+j);
						pthread_mutex_unlock(&mutex_erase);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
				}
			}
		}
		pthread_mutex_unlock(&mutex3);
		sleep(1);
		pthread_mutex_lock(&mutex2);
		// Sprawdzenie kolejki ze studentami, ktorzy maja dwa wpisy
		sz= kolejka2.size();
		if(!kolejka2.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke2"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka2[j]&(1<<id))
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka2)"<<endl;
						kolejka2[j]&=~(1<<id); // odznaczamy profesora
						pthread_mutex_lock(&mutex3);
						kolejka3.push_back(kolejka2[j]);
						pthread_mutex_unlock(&mutex3);
						pthread_mutex_lock(&mutex_erase);
						kolejka2.erase(kolejka2.begin()+j);
						pthread_mutex_unlock(&mutex_erase);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}
				}
			}
		}
		pthread_mutex_unlock(&mutex2);
		sleep(1);
		pthread_mutex_lock(&mutex1);
		// Sprawdzenie kolejki ze studentami, ktorzy maja jeden wpisy
		sz= kolejka1.size();
		if(!kolejka1.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke1"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka1[j]&(1<<id))
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka1)"<<endl;
						kolejka1[j]&=~(1<<id); // odznaczamy profesora
						pthread_mutex_lock(&mutex2);
						kolejka2.push_back(kolejka1[j]);
						pthread_mutex_unlock(&mutex2);
						pthread_mutex_lock(&mutex_erase);
						kolejka1.erase(kolejka2.begin()+j);
						pthread_mutex_unlock(&mutex_erase);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}	
				}
			}
		}
        pthread_mutex_unlock(&mutex1);
		sleep(1);
		pthread_mutex_lock(&mutex0);
		// Sprawdzenie kolejki ze studentami, ktorzy nie maja wpisow
		sz= kolejka0.size();
		if(!kolejka0.empty())
		{cout <<"Profesor: "<<id<<"  sprawdza kolejke0"<<endl;
			for (unsigned j=0; j<sz; j++)
			{
				for(int i=0;i<4;i++)
				{
					if(kolejka0[j]&(1<<id))
					{cout <<"Profesor: "<<id<<"  znalazl swoje id(kolejka1)"<<endl;
						kolejka0[j]&=~(1<<id); // odznaczamy profesora
						pthread_mutex_lock(&mutex1);
						kolejka1.push_back(kolejka0[j]);
						pthread_mutex_unlock(&mutex1);
						pthread_mutex_lock(&mutex_erase);
						kolejka0.erase(kolejka2.begin()+j);
						pthread_mutex_unlock(&mutex_erase);
						cout <<"Profesor: "<<id<<"  Dodal swoj wpis"<<endl;
					}	
				}
			}
		}
        pthread_mutex_unlock(&mutex0);
		sleep(1);
    }
}
/*
 * Kod Portiera.
 *
 * Utrzymuje kolejke zerowa by bylo w niej przynajmnie 10 studentów
 * Jezeli jest mniej niz 10 studentow dorabia 10 nowych
 */
void *Portier(void * arg)
{
	cout <<"Portier zaczal swoja prace"<<endl;
	int abc;
	while(1)
	{
		pthread_mutex_lock(&mutex0);
		if(kolejka0.size()<10)
		{
			for(int i=0;i<10;i++)
			{
				abc=UtworzStudenta();
				kolejka1.push_back(abc);
			}cout <<"Portier utworzyl nowych studentow"<<endl;
		}
		pthread_mutex_unlock(&mutex0);
		sleep(2);
	}
}

Zobacz pozostałe 3 komentarze
_13th_Dragon
Jeden portier nie będzie nadążał tworzyć studentów, bo profesorów jest 10.
SH
to już zauważyłem, że nie nadąża ;D
_13th_Dragon
Tak jak pisałem poprzednio, jak profesor nic nie znalazł w żadnej z kolejek to ma sam sobie studenta rekrutować.
SH
yhym tak sobie zrobię ;P
SH
@_13th_Dragon błąd który powodował mi segmentation fault był spowodowany literówką ;D usuwałem element znajdujący się w liście drugiej z listy trzeciej
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)