==============================================================
  Experiment 11: Readers-Writers Problem Using Semaphores
==============================================================
  [Back to Index]
--------------------------------------------------------------

THEORY:
  A shared resource (database, file, variable) is accessed by
  two types of processes:

  Readers:
    - Only read the data
    - Do not modify it
    - Many readers can read simultaneously

  Writers:
    - Modify the data
    - Must have exclusive access
    - No other reader or writer can access the resource
      while a writer is writing

  The main goal is to ensure correctness and consistency
  of shared data.

--------------------------------------------------------------

CONSTRAINTS:
  - Multiple readers can read at the same time.
  - Only one writer can write at a time.
  - No reader should read while writer is writing.
  - No two writers should write at the same time.

==============================================================
  PART 1: Reader Priority
==============================================================

READER ALGORITHM (Reader Priority):
  wait(mutex)
  read_count++
  if read_count == 1:
       wait(rw_mutex)    // first reader locks writers out
  signal(mutex)

  READ DATA

  wait(mutex)
  read_count--
  if read_count == 0:
       signal(rw_mutex)  // last reader unlocks resource
  signal(mutex)

WRITER ALGORITHM (Reader Priority):
  wait(rw_mutex)        // Only one writer at a time
  WRITE DATA
  signal(rw_mutex)

--------------------------------------------------------------

SOURCE CODE: reader_writer_reader_priority.c

--------------------------------------------------------------
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t rw_mutex;   // Controls access to shared resource
sem_t mutex;      // Controls read_count access
int read_count = 0;

void *reader(void *arg) {
    int id = *(int *)arg;

    sem_wait(&mutex);
    read_count++;
    if (read_count == 1)
        sem_wait(&rw_mutex);  // First reader blocks writers
    sem_post(&mutex);

    // Critical Section
    printf("Reader %d is READING\n", id);
    sleep(1);
    printf("Reader %d is DONE reading\n", id);

    sem_wait(&mutex);
    read_count--;
    if (read_count == 0)
        sem_post(&rw_mutex);  // Last reader releases writers
    sem_post(&mutex);

    return NULL;
}

void *writer(void *arg) {
    int id = *(int *)arg;

    sem_wait(&rw_mutex);  // Writer needs exclusive access

    // Critical Section
    printf("\tWriter %d is WRITING\n", id);
    sleep(2);
    printf("\tWriter %d is DONE writing\n", id);

    sem_post(&rw_mutex);

    return NULL;
}

int main() {
    pthread_t r[5], w[5];
    int ids[5];

    sem_init(&rw_mutex, 0, 1);
    sem_init(&mutex, 0, 1);

    for (int i = 0; i < 5; i++)
        ids[i] = i + 1;

    for (int i = 0; i < 5; i++) {
        pthread_create(&r[i], NULL, reader, &ids[i]);
        pthread_create(&w[i], NULL, writer, &ids[i]);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(r[i], NULL);
        pthread_join(w[i], NULL);
    }

    sem_destroy(&rw_mutex);
    sem_destroy(&mutex);

    return 0;
}
--------------------------------------------------------------

COMPILE: gcc -o rw_reader reader_writer_reader_priority.c -lpthread

==============================================================
  PART 2: Writer Priority
==============================================================

READER ALGORITHM (Writer Priority):
  Wait on queue
  Wait on mutex
  Increment read_count
  If read_count == 1, wait on rw_mutex
  Signal mutex
  Signal queue
  Read the shared data
  Wait on mutex
  Decrement read_count
  If read_count == 0, signal rw_mutex
  Signal mutex

WRITER ALGORITHM (Writer Priority):
  Wait on queue
  Wait on rw_mutex
  Write to the shared data
  Signal rw_mutex
  Signal queue

--------------------------------------------------------------

SOURCE CODE: reader_writer_writer_priority.c

--------------------------------------------------------------
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t mutex;        // Protects read_count
sem_t rw_mutex;     // Exclusive access to shared resource
sem_t queue;        // Enforces writer priority

int read_count = 0;

void *reader(void *arg) {
    int id = *(int *)arg;

    sem_wait(&queue);          // Block if writer waiting
    sem_wait(&mutex);

    read_count++;
    if (read_count == 1)
        sem_wait(&rw_mutex);   // First reader blocks writers

    sem_post(&mutex);
    sem_post(&queue);          // Allow others to queue

    // Critical Section (Reading)
    printf("Reader %d is READING\n", id);
    sleep(1);
    printf("Reader %d has FINISHED READING\n", id);

    sem_wait(&mutex);
    read_count--;
    if (read_count == 0)
        sem_post(&rw_mutex);   // Last reader releases writer
    sem_post(&mutex);

    return NULL;
}

void *writer(void *arg) {
    int id = *(int *)arg;

    sem_wait(&queue);          // Writer gets priority
    sem_wait(&rw_mutex);       // Exclusive access

    // Critical Section (Writing)
    printf("\tWriter %d is WRITING\n", id);
    sleep(2);
    printf("\tWriter %d has FINISHED WRITING\n", id);

    sem_post(&rw_mutex);
    sem_post(&queue);

    return NULL;
}

int main() {
    pthread_t readers[5], writers[5];
    int id[5];

    sem_init(&mutex, 0, 1);
    sem_init(&rw_mutex, 0, 1);
    sem_init(&queue, 0, 1);

    for (int i = 0; i < 5; i++) {
        id[i] = i + 1;
        pthread_create(&readers[i], NULL, reader, &id[i]);
        pthread_create(&writers[i], NULL, writer, &id[i]);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(readers[i], NULL);
        pthread_join(writers[i], NULL);
    }

    sem_destroy(&mutex);
    sem_destroy(&rw_mutex);
    sem_destroy(&queue);

    return 0;
}
--------------------------------------------------------------

COMPILE: gcc -o rw_writer reader_writer_writer_priority.c -lpthread

==============================================================
  [Prev: Exp 10]  |  [Next: Exp 12]
==============================================================