1

I'm wondering if it's possible to alter the readers and writers problem so that the writers become incrementers and decrementers? My plan is to create a random number of incrementer, decrementer and reader threads using the pthreads and then keep a running total in a counter so that any time an incrementer accesses the data, the counter goes up 1 and vice versa. So to explain, the code would work in the same way as the readers and writers with the writer getting exclusive access to the data. But the thread would print out for writer - whether it was an incrementer or decrementer, and the current value stored in the counter. For reader - the value that was stored in the counter when that thread accessed it.

This is the code I currently have, but it obviously doesn't factor in the separate incrementers and decrementers.

#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include "sem_ops.h"
#define READERS 8
#define WRITERS 3

int counter = 0;
int readers = 0;
int reader_sem;
int counter_sem;

void *writerfunc( void * arg ) { 
  int *me;

  me = (int *) arg;

  srand( time( NULL ) );
  sleep( rand() % 5 );   
  P( counter_sem );
  counter++;
  printf( "Writer Thread %d running!! counter = %d\n", *me, counter );
  V( counter_sem );

  pthread_exit( NULL );
}

void *readerfunc( void * arg ) { 
  int *me;

  me = (int *) arg;

  P( reader_sem );
  readers++;
  if( readers == 1 )
    P( counter_sem );
  V( reader_sem );

  srand( time( NULL ) );
  sleep( rand() % 5 );   
  printf( "Reader Thread %d running!! counter = %d\n", *me, counter );

  P( reader_sem );
  readers--;
  if( readers == 0 )
    V( counter_sem );
  V( reader_sem );

  pthread_exit( NULL );
}

int main( void ) {
  int i;
  pthread_t rtid[READERS];
  int readerid[READERS];
  pthread_t wtid[WRITERS];
  int writerid[WRITERS];

  counter = 0;
  reader_sem = semtran( IPC_PRIVATE );
  counter_sem = semtran( IPC_PRIVATE );
  V( counter_sem );  
  V( reader_sem );   

  for( i=0; i<READERS; i++ ) 
    readerid[i] = i;
  for( i=0; i<WRITERS; i++ ) 
    writerid[i] = i;
  for( i=0; i<WRITERS; i++ ) 
    pthread_create( &wtid[i], NULL, writerfunc, (void *) &writerid[i] );
  for( i=0; i<READERS; i++ ) 
    pthread_create( &rtid[i], NULL, readerfunc, (void *) &readerid[i] );
  for( i=0; i<WRITERS; i++ ) 
    pthread_join( wtid[i], NULL );
  for( i=0; i<READERS; i++ )
    pthread_join( rtid[i], NULL );
  return 0;
}

I'm just wondering if this is possible, and if so any tips on how to go out updating my code would be really appreciated. Thanks!

btoohey
  • 141
  • 1
  • 1
  • 12
  • 1
    What is your specific question? The "Is it possible?" gets a "Yes, surely, with some effort and experience." as an answer. – Yunnosch Jul 30 '17 at 06:59
  • 1
    For one, unless you're specifically trying to produce a repeatable pseudo-random sequence, `srand()` should be called once for the life of your process; not once per thread. Secondly, take heed that `rand()` is neither reentrant nor thread-safe per the standard. [See this question for more information](https://stackoverflow.com/questions/6161322/using-stdlibs-rand-from-multiple-threads). – WhozCraig Jul 30 '17 at 07:09
  • See also [`srand()` — why call it only once?](http://stackoverflow.com/questions/7343833/srand-why-call-it-only-once/). Note that the [`drand48()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html) family of functions includes variants that can give different sequences per thread if desired. Note that you should consider reproducibility carefully too — the ability to control the seed(s) used so that you actually can reproduce the results of run if need be. – Jonathan Leffler Jul 30 '17 at 07:31

0 Answers0