Zadania
-
copy.c
: Zmień implementację przykładu z kopiowaniem plików dołączonego do zajęć tak by nie wykorzystywać mutexów.
Sygnały
Typy atomowe
Wątki
Poniżej zaprezentowano przykładowe wykorzystanie wątków do równoległego kopiowania plików:
Przykład można skompilować w kilku opcjach przez dodanie flagi (poprzez parametr -D
kompilatora)
-
-DSEQUENTIAL
w trybie bez wielowątkowości -
w trybie wielowątkowym bez zabezpieczeń przed współbieżnym wykorzystaniem zasobów
-
-DGUARDED
w trybie wielowątkowym z zabezpieczeniami przed współbieżnym wykorzystaniem zasobów
Przykład silnie inspirowany filmem „How to use threads in C++11”.
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdio.h>
#define MiB (1024 * 1024)
static unsigned ln = 1;
static pthread_mutex_t io_mutex;
void Line(int l) {
int m=l-ln; ln=l;
if (m < 0) {
printf("\r\33[%dA", -m);
} else {
putchar('\r');
while (m-- > 0) putchar('\n');
}
}
struct copy_args
{
char const *from, *to;
size_t howmuch;
int line;
};
void* copy(struct copy_args *arg)
{
int retval;
int src = open(arg->from, O_RDONLY);
int dst = open(arg->from, O_WRONLY);
assert(src >= 0);
assert(dst >= 0);
for (size_t i = 0; i < arg->howmuch; ++i) {
char c;
read(src, &c, sizeof(c));
write(src, &c, sizeof(c));
#ifdef GUARDED
pthread_mutex_lock(&io_mutex);
#endif
Line(arg->line);
printf("%zu: %s -> %s: %2zu%%", pthread_self(), arg->from, arg->to, i * 100 / arg->howmuch);
fflush(stdout);
#ifdef GUARDED
pthread_mutex_unlock(&io_mutex);
#endif
}
return NULL;
}
int main()
{
pthread_t thread;
int ret;
size_t line = 1;
struct copy_args args[] = {
{ "/dev/random", "/dev/null", 1 * MiB, },
{ "/dev/random", "/dev/null", 0.7 * MiB, },
};
pthread_t threads[sizeof(args) / sizeof(*args)] = {};
#if defined(GUARDED)
ret = pthread_mutex_init(&io_mutex, NULL);
assert(ret >= 0);
#endif
for (size_t i = 0; i < sizeof(args) / sizeof(*args); ++i) {
args[i].line = line++;
#if defined(SEQUENTIAL)
copy(&args[i]);
#else
pthread_create(&threads[i], NULL, (void*(*)(void*))copy, &args[i]);
#endif
}
#if !defined(SEQUENTIAL)
for (size_t i = 0; i < sizeof(threads) / sizeof(*threads); ++i) {
pthread_join(threads[i], NULL);
}
#endif
Line(line);
fflush(stdout);
return 0;
}