Last active
June 12, 2018 18:28
-
-
Save j000/f26db502605906af5f1ccf822d62587e to your computer and use it in GitHub Desktop.
Czytelnicy i pisarze
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _REENTRANT | |
#define _XOPEN_SOURCE 700 | |
#include <pthread.h> /* wątki */ | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <stdlib.h> // rand | |
#include <time.h> // time | |
#define PISARZE 2 | |
#define CZYTELNICY 10 | |
// man 3 pthread_mutex_destroy | |
pthread_mutex_t mutex_dostep = PTHREAD_MUTEX_INITIALIZER; | |
pthread_mutex_t mutex_czytelnicy = PTHREAD_MUTEX_INITIALIZER; | |
pthread_mutex_t mutex_kolejnosc = PTHREAD_MUTEX_INITIALIZER; | |
unsigned liczba_czytelnikow = 0; | |
// mój system narzeka, że usleep nie istnieje | |
// jeżeli usleep(1) działa: NIE KOPIUJ | |
#if _POSIX_VERSION >= 200800L | |
#define usleep my_usleep | |
__attribute__((always_inline)) inline | |
void usleep(unsigned long microseconds) { | |
struct timespec delay = { | |
.tv_sec = microseconds / 1000000l, | |
.tv_nsec = (microseconds % 1000000l) * 1000 | |
}; | |
while (nanosleep(&delay, &delay) == -1); | |
} | |
#endif | |
void *czytelnik(void *costam) { | |
int i = 5; | |
usleep(2000000 * drand48()); // losowe czekanie | |
while (--i) { | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
pthread_mutex_lock(&mutex_kolejnosc); // kolejka | |
pthread_mutex_lock(&mutex_czytelnicy); // dostęp do licznika czytelników | |
if (liczba_czytelnikow == 0) // pierwszy czytelnik | |
pthread_mutex_lock(&mutex_dostep); // uzyskuje dostęp do biblioteki | |
++liczba_czytelnikow; | |
pthread_mutex_unlock(&mutex_czytelnicy); // koniec dostępu do licznika | |
pthread_mutex_unlock(&mutex_kolejnosc); // koniec kolejki, jesteśmy w środku | |
// czytaj... | |
printf("Czytelnik\n"); | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
printf("Poczytałem\n"); | |
pthread_mutex_lock(&mutex_czytelnicy); // dostęp do licznika czytelników | |
--liczba_czytelnikow; | |
if (liczba_czytelnikow == 0) // ostatni czytelnik | |
pthread_mutex_unlock(&mutex_dostep); // gasi światłoi ;) | |
pthread_mutex_unlock(&mutex_czytelnicy); // koniec dostępu do licznika | |
} | |
return NULL; | |
} | |
void *pisarz(void *costam) { | |
int i = 5; | |
usleep(2000000 * drand48()); // losowe czekanie | |
while (--i) { | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
pthread_mutex_lock(&mutex_kolejnosc); // kolejka | |
pthread_mutex_lock(&mutex_dostep); // dostęp do biblioteki | |
pthread_mutex_unlock(&mutex_kolejnosc); // koniec kolejki, jesteśmy w środku | |
// zapisz... | |
printf(" *** Pisarz ***\n"); | |
usleep(2000000 * drand48()); | |
printf(" *** Zapisane ***\n"); | |
pthread_mutex_unlock(&mutex_dostep); // wpuść kogoś innego do biblioteki | |
} | |
return NULL; | |
} | |
int main() { | |
srand48(time(NULL)); | |
pthread_t pisarze[PISARZE] = {0}; | |
pthread_t czytelnicy[CZYTELNICY] = {0}; | |
// tworzymy wątki pisarzy | |
for (unsigned i = 0; i < PISARZE; ++i) { | |
if (pthread_create(&(pisarze[i]), NULL, pisarz, NULL)) { | |
printf("pthread_create(pisarz) failed\n"); | |
_exit(1); | |
} | |
usleep(100); | |
} | |
// tworzymy wątki czytelników | |
for (unsigned i = 0; i < CZYTELNICY; ++i) { | |
if (pthread_create(&(czytelnicy[i]), NULL, czytelnik, NULL)) { | |
printf("pthread_create(czytelnik) failed\n"); | |
_exit(1); | |
} | |
usleep(100); | |
} | |
usleep(1000000); | |
// czekamy na wątki pisarzy | |
for (unsigned i = 0; i < PISARZE; ++i) { | |
if (pthread_join(pisarze[i], NULL)) { | |
printf("pthread_join() failed\n"); | |
_exit(1); | |
} | |
} | |
// czekamy na wątki czytelników | |
for (unsigned i = 0; i < CZYTELNICY; ++i) { | |
if (pthread_join(czytelnicy[i], NULL)) { | |
printf("pthread_join() failed\n"); | |
_exit(1); | |
} | |
} | |
pthread_mutex_destroy(&mutex_czytelnicy); | |
pthread_mutex_destroy(&mutex_dostep); | |
pthread_mutex_destroy(&mutex_kolejnosc); | |
return 0; | |
} | |
// vim: tabstop=4 shiftwidth=0 noexpandtab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _REENTRANT | |
#define _XOPEN_SOURCE 700 | |
#include <pthread.h> /* wątki */ | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <stdlib.h> // rand | |
#include <time.h> // time | |
#define PISARZE 2 | |
#define CZYTELNICY 10 | |
// man 3 pthread_rwlock_destroy | |
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; | |
// mój system narzeka, że usleep nie istnieje | |
// jeżeli usleep(1) działa: NIE KOPIUJ | |
#if _POSIX_VERSION >= 200800L | |
#define usleep my_usleep | |
__attribute__((always_inline)) inline | |
void usleep(unsigned long microseconds) { | |
struct timespec delay = { | |
.tv_sec = microseconds / 1000000l, | |
.tv_nsec = (microseconds % 1000000l) * 1000 | |
}; | |
while (nanosleep(&delay, &delay) == -1); | |
} | |
#endif | |
void *czytelnik(void *costam) { | |
int i = 5; | |
usleep(2000000 * drand48()); // losowe czekanie | |
while (--i) { | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
pthread_rwlock_rdlock(&rwlock); | |
// czytaj... | |
printf("Czytelnik\n"); | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
printf("Poczytałem\n"); | |
pthread_rwlock_unlock(&rwlock); | |
} | |
return NULL; | |
} | |
void *pisarz(void *costam) { | |
int i = 5; | |
usleep(2000000 * drand48()); // losowe czekanie | |
while (--i) { | |
// rand itp. nie powinny być uzywane równocześnie z kilku wątków | |
// grozi błędem | |
usleep(2000000 * drand48()); | |
pthread_rwlock_wrlock(&rwlock); | |
// zapisz... | |
printf(" *** Pisarz ***\n"); | |
usleep(2000000 * drand48()); | |
printf(" *** Zapisane ***\n"); | |
pthread_rwlock_unlock(&rwlock); | |
} | |
return NULL; | |
} | |
int main() { | |
srand48(time(NULL)); | |
pthread_t pisarze[PISARZE] = {0}; | |
pthread_t czytelnicy[CZYTELNICY] = {0}; | |
// tworzymy wątki pisarzy | |
for (unsigned i = 0; i < PISARZE; ++i) { | |
if (pthread_create(&(pisarze[i]), NULL, pisarz, NULL)) { | |
printf("pthread_create(pisarz) failed\n"); | |
_exit(1); | |
} | |
usleep(100); | |
} | |
// tworzymy wątki czytelników | |
for (unsigned i = 0; i < CZYTELNICY; ++i) { | |
if (pthread_create(&(czytelnicy[i]), NULL, czytelnik, NULL)) { | |
printf("pthread_create(czytelnik) failed\n"); | |
_exit(1); | |
} | |
usleep(100); | |
} | |
usleep(1000000); | |
// czekamy na wątki pisarzy | |
for (unsigned i = 0; i < PISARZE; ++i) { | |
if (pthread_join(pisarze[i], NULL)) { | |
printf("pthread_join() failed\n"); | |
_exit(1); | |
} | |
} | |
// czekamy na wątki czytelników | |
for (unsigned i = 0; i < CZYTELNICY; ++i) { | |
if (pthread_join(czytelnicy[i], NULL)) { | |
printf("pthread_join() failed\n"); | |
_exit(1); | |
} | |
} | |
pthread_rwlock_destroy(&rwlock); | |
return 0; | |
} | |
// vim: tabstop=4 shiftwidth=0 noexpandtab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Jarosław Rymut | |
### 'private' wymaga przynajmniej GNU make 3.82 z 2010 roku ### | |
# numer zestawu | |
zestaw := $(notdir $(lastword $(CURDIR))) | |
# nazwa spakowanego pliku | |
tar := Rymut_$(zestaw).tar.gz | |
# flagi | |
CFLAGS := -std=c99 -O2 -Wall -Wextra | |
ARFLAGS += -c -s | |
ifeq ($(shell $(CC) -dumpversion),4.7) | |
# welcome to 2012 | |
# -Wpedantic is available since gcc 4.8 | |
CFLAGS += -pedantic | |
else | |
CFLAGS += -Wpedantic | |
endif | |
# CFLAGS += -fPIC -fPIE | |
# LDFLAGS += -fPIC -fPIE -pie | |
# PIC > PIE > no-pie | |
CFLAGS += -fPIC | |
LDFLAGS += -fPIC -pie | |
LDLIBS += -Wl,-R. | |
LOADLIBES += -lpthread | |
CFLAGS += -flto | |
HELPERS := sem.c shmem.c | |
FILES := $(filter-out $(HELPERS),$(wildcard *.c)) | |
.PHONY: all | |
all: $(FILES:.c=.x) | |
.PHONY: clean | |
clean: | |
-$(RM) $(FILES:.c=.x) $(tar) lib* | |
.PHONY: tar | |
tar: | |
# poprawka na błąd 'file changed as we read it' | |
[ -f $(tar) ] || touch $(tar) | |
tar -caf ./$(tar) --exclude=$(tar) --exclude=*.x --exclude=.* --exclude=lib* -C .. $(zestaw) | |
# kopia wbudowanej reguły, z nowym rozszerzeniem | |
%.x: private LDFLAGS += -fPIC -pie | |
%.x: %.o | |
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) | |
# kopia wbudowanej reguły, z nowym rozszerzeniem | |
lib%.so: private LDFLAGS += -shared | |
lib%.so: %.o | |
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION) | |
#################### | |
# wszystko zależy od Makefile | |
$(FILES:.c=.o) $(HELPERS:.c=.o): Makefile | |
#################### | |
# make może usunąć pliki "tymczasowe" | |
.INTERMEDIATE: $(HELPERS:.c=.o) $(FILES:.c=.o) | |
#################### | |
# # wszystko potrzebuje biblioteki | |
# $(FILES:.c=.x): private LDLIBS += -L. -lsem -lshmem | |
# | |
# # wszystko zależy od shmem.h | |
# $(FILES:.c=.o): sem.h | libsem.so libshmem.so | |
# sem.o: sem.h | |
# shmem.o: shmem.h |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment