Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

T3

.c
Скачиваний:
18
Добавлен:
19.06.2023
Размер:
8.85 Кб
Скачать
/*
 * Выполнил: —, 93—
 * Задание: 3 Поставщик – Потребитель
 * Дата выполнения: 17 марта 2023 г.
 * Версия: 0.1
 *
 * Скрипт для компиляции и запуска программы:
 *     cc T3.c -o T3
 *     ./T3
 */
// ------------------------------------------- //
/*
 * Общее описание программы:
 *      Создаются потоки поставщика и потребителя, которые
 *      циклически изменяют общую переменную с использованием
 *      механизмов семафоров или условных переменных.
 *
 *      Введите "s" в консоль для использования семафора
 *      или что-то другое для использования условных переменных.
 *
 *      Выводимые сообщения в консоли содержат в себе информацию
 *      о типе действия, новом значении в буфере, времени начала
 *      и окончания выполнения задачи.
 */
// ------------------------------------------- //


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>

#define CONSUME_SLEEP_TIME 3
#define SUPPLY_SLEEP_TIME 1
#define BUFFER_LIMIT 3

#define SEMAPHORE 1
#define CONDITIONAL_VARIABLE 2

// Вариант задания
int type;

// Время запуска программы
double initial_time = 0;

// Синхронизирующие структуры
sem_t semaphore;
pthread_cond_t supplier_cond;
pthread_cond_t consumer_cond;
pthread_mutex_t mutex;

// Общая переменная
int buffer = 0;

// Возвращает время в секундах с момента initial_time.
double get_time() {
    struct timeval t;
    gettimeofday(&t, NULL);
    return (double) t.tv_sec + (double) t.tv_usec / 1000000 - initial_time;
}

// Поток потребителя
void *consumer_routine(void *args) {
    double t0;
    double t1;
    int b;

    while (1) {
        if (type == SEMAPHORE) {
            if (buffer > 0) {
                // Блокировка семафора или ожидание, пока он освободиться потребителем
                sem_wait(&semaphore);
                // Критическая секция. Замеры времени и изменение значения в буфере
                t0 = get_time();
                b = --buffer;
                t1 = get_time();
                // Освобождение семафора
                sem_post(&semaphore);
                // Вывод значения в буфере и времени начала и окончания задачи
                printf("Consume (%d): %f → %f\n", b, t0, t1);
            }
        }
        if (type == CONDITIONAL_VARIABLE) {
            // Захват мьютекса
            pthread_mutex_lock(&mutex);
            // Если буфер пуст, освобождение мьютекса и ожидание завершения задачи поставщиком,
            // которая просигнализирует об увеличении значения в буфере
            if (buffer == 0) pthread_cond_wait(&consumer_cond, &mutex);
            // Критическая секция. Замеры времени и изменение значения в буфере
            t0 = get_time();
            b = --buffer;
            t1 = get_time();
            // Сигнализирование об уменьшении значения в буфере
            pthread_cond_signal(&supplier_cond);
            // Освобождение мьютекса
            pthread_mutex_unlock(&mutex);
            // Вывод значения в буфере и времени начала и окончания задачи
            printf("Consume (%d): %f → %f\n", b, t0, t1);
        }
        sleep(CONSUME_SLEEP_TIME);
    }
}

// Поток поставщика
void *supplier_routine(void *args) {
    double t0;
    double t1;
    int b;

    while (1) {
        if (type == SEMAPHORE) {
            if (buffer < BUFFER_LIMIT) {
                // Блокировка семафора или ожидание, пока он освободиться потребителем
                sem_wait(&semaphore);
                // Критическая секция. Замеры времени и изменение значения в буфере
                t0 = get_time();
                b = ++buffer;
                t1 = get_time();
                // Освобождение семафора
                sem_post(&semaphore);
                // Вывод значения в буфере и времени начала и окончания задачи
                printf("Supply (%d): %f → %f\n", b, t0, t1);
            }
        }
        if (type == CONDITIONAL_VARIABLE) {
            // Захват мьютекса
            pthread_mutex_lock(&mutex);
            // Если буфер полон, освобождение мьютекса и ожидание завершения задачи потребителем,
            // которая просигнализирует об уменьшении значения в буфере
            if (buffer == BUFFER_LIMIT) pthread_cond_wait(&supplier_cond, &mutex);
            // Критическая секция. Замеры времени и изменение значения в буфере
            t0 = get_time();
            b = ++buffer;
            t1 = get_time();
            // Сигнализирование об увеличении значения в буфере
            pthread_cond_signal(&consumer_cond);
            // Освобождение мьютекса
            pthread_mutex_unlock(&mutex);
            // Вывод значения в буфере и времени начала и окончания задачи
            printf("Supply (%d): %f → %f\n", b, t0, t1);
        }
        sleep(SUPPLY_SLEEP_TIME);
    }
}

int main(int argc, char *argv[]) {
    // Выбор варианта задания
    type = getchar() == 's' ? SEMAPHORE : CONDITIONAL_VARIABLE;

    // Установка времени начала отсчёта
    initial_time = get_time();

    // Инициализация синхронизирующих структур
    if (type == SEMAPHORE) {
        printf("Semaphore\n");
        sem_init(&semaphore, 0, 1);
    }
    if (type == CONDITIONAL_VARIABLE) {
        printf("Conditional variable\n");
        pthread_cond_init(&supplier_cond, NULL);
        pthread_cond_init(&consumer_cond, NULL);
        pthread_mutex_init(&mutex, NULL);
    }

    // Создание и запуск потоков
    pthread_t consumer_thread;
    pthread_t supplier_thread;
    pthread_create(&consumer_thread, NULL, &consumer_routine, NULL);
    pthread_create(&supplier_thread, NULL, &supplier_routine, NULL);
    pthread_join(consumer_thread, NULL);
    pthread_join(supplier_thread, NULL);
    return EXIT_SUCCESS;
}

// ----------------------------------------//
/*
s
Semaphore
Supply (1): 0.000794 → 0.000794
Supply (2): 1.000891 → 1.000891
Supply (3): 2.001403 → 2.001404
Consume (2): 3.000295 → 3.000295
Supply (3): 3.001480 → 3.001480
Consume (2): 6.000719 → 6.000720
Supply (3): 6.002536 → 6.002537
Consume (2): 9.001122 → 9.001122
Supply (3): 9.003046 → 9.003046
Consume (2): 12.001577 → 12.001577
Supply (3): 12.004344 → 12.004345
Consume (2): 15.001982 → 15.001983
Supply (3): 15.005773 → 15.005773
Consume (2): 18.002177 → 18.002177
Supply (3): 18.006891 → 18.006892
*/

/*
c
Conditional variable
Supply (1): 0.000159 → 0.000160
Consume (0): 0.000207 → 0.000207
Supply (1): 1.000362 → 1.000362
Supply (2): 2.000901 → 2.000901
Consume (1): 3.000575 → 3.000575
Supply (2): 3.001011 → 3.001011
Supply (3): 4.001823 → 4.001823
Consume (2): 6.009274 → 6.009274
Supply (3): 6.009328 → 6.009328
Consume (2): 9.011266 → 9.011267
Supply (3): 9.011464 → 9.011464
Consume (2): 12.011576 → 12.011577
Supply (3): 12.011617 → 12.011617
Consume (2): 15.012196 → 15.012196
Supply (3): 15.012291 → 15.012291
Consume (2): 18.012841 → 18.012841
Supply (3): 18.012914 → 18.012914
*/
Соседние файлы в предмете Системы реального времени