106 lines
2.7 KiB
C
106 lines
2.7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
|
|
#include "buff.h"
|
|
|
|
#define ERR_PTR ((void *)1)
|
|
#define VOID_CAST(num) ((void *) num)
|
|
|
|
#define N_PRODUCERS 16
|
|
#define N_CONSUMERS 1
|
|
#define KEY_LEN 32 // len in chars
|
|
|
|
const char key_syms[] = "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ"
|
|
"1234567890";
|
|
|
|
#define ALPHABET_SIZE (sizeof(key_syms) - 1)
|
|
|
|
pthread_t consumers[N_CONSUMERS] = {0};
|
|
pthread_t producers[N_PRODUCERS] = {0};
|
|
|
|
/**
|
|
* Создает "ключи" - наборы "случайных" символов из
|
|
* списка допустимых
|
|
*/
|
|
void get_key(char key_dest[KEY_LEN])
|
|
{
|
|
for (size_t i = 0; i < KEY_LEN; i++) {
|
|
size_t sym_idx = rand() % ALPHABET_SIZE;
|
|
key_dest[i] = key_syms[sym_idx];
|
|
}
|
|
}
|
|
|
|
volatile bool run = true;
|
|
|
|
void *producer_routine(void *arg)
|
|
{
|
|
size_t pidx = (size_t) arg;
|
|
struct message msg = {0};
|
|
while (run) {
|
|
get_key(msg.msg);
|
|
if (buf_push(&msg)) pthread_exit(ERR_PTR);
|
|
printf("[p%lu] pushed new key\n", pidx);
|
|
sleep(1);
|
|
}
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
void *consumer_routine(void *arg)
|
|
{
|
|
size_t cidx = (size_t) arg;
|
|
struct message msg = {0};
|
|
while (run) {
|
|
if (buf_consume(&msg)) pthread_exit(ERR_PTR);
|
|
printf("[c%lu] obtained key %s\n", cidx, msg.msg);
|
|
sleep(1);
|
|
}
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
if (buf_init()) {
|
|
printf("failed to init work buffer\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
for (size_t i = 0; i < N_PRODUCERS; i++) {
|
|
if (pthread_create(&producers[i], NULL,
|
|
producer_routine, VOID_CAST(i))) {
|
|
printf("Failed to create enough consumer threads\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
for (size_t i = 0; i < N_CONSUMERS; i++) {
|
|
if (pthread_create(&consumers[i], NULL,
|
|
consumer_routine, VOID_CAST(i))) {
|
|
printf("Failed to create enough consumer threads\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
sleep(10);
|
|
run = false;
|
|
|
|
void *ret = NULL;
|
|
for (size_t i = 0; i < N_PRODUCERS; i++) {
|
|
if (pthread_join(producers[i], &ret)) {
|
|
printf("failed to join producer");
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
for (size_t i = 0; i < N_CONSUMERS; i++) {
|
|
if (pthread_join(consumers[i], &ret)) {
|
|
printf("failed to join consumer");
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
// не используем разделяемые ресурсы, так что код возврата
|
|
// можно игнорировать, linux справится
|
|
buf_deinit();
|
|
return EXIT_SUCCESS;
|
|
}
|