Tushar Goel
Tushar Goel

Reputation: 35

Multple writer single reader synchronization in multiple process environment?

I have a project in which several writers(using multi thread) write using one process and single reader(Single thread) reads this write through another process. Writer and reader keep doing the same. Writer writes variable lines of data in every write so i cannot use buffer. I think to use either memory map files or single file in which i can write this.

I am confused for synchronization. As am doing this in 2 process so cannot use condition variables so need to use semaphore only.

Now if i use semaphore then several writer write at same time so its overwrite previous data write by another writer and when reader reads it will read only latest write and i will lost all previous write.I want reader should read every write happened. Some delay is acceptable.

I can also try one thing write all in a file then sleep threads for some time and read them during that sleep but by doing this i may lost some data which may arrived during sleep time.

Any idea how to implement the same? Any help is great. I am using C and Linux platform. So kindly suggest related to C and Linux/Unix.

Update1: I have done following steps for semaphore:

                       semget(key,2,flag)  //define 2 semaphore
         semctl(semid,0,SETVAL,0)  //Initialize value for semaphore 0
         semctl(semid,1,SETVAL,0)  //Initialize value for semaphore 0

         writer_lock(semid)  //writer lock
              struct sembuf action[2] ;
            action[0].sem_num = 0;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = 0 ;
            action[1].sem_num = 1;
            action[1].sem_flg = SEM_UNDO;
            action[1].sem_op  = +1 ;
              semop(sem_id,action,2);

          release_writer_lock
              struct sembuf action[1] ;
            action[0].sem_num = 1;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = -1 ;
             semop(sem_id,action,1);

         reader_lock(semid)
               struct sembuf action[2] ;
            action[0].sem_num = 1;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = 0 ;
            action[1].sem_num = 0;
            action[1].sem_flg = SEM_UNDO;
            action[1].sem_op  = +1 ;
             semop(sem_id,action,2) 


          release_reader_lock
              struct sembuf action[1] ;
            action[0].sem_num = 0;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = -1 ;
             semop(sem_id,action,1);

        ** writer end***
        writer_lock(semid)
          /* my work*/
        release_writer_lock(semid)


        ** reader end***
        reader_lock(semid)
          /* read and clear */
        release_reader_lock(semid)

Upvotes: 0

Views: 3018

Answers (2)

ravi
ravi

Reputation: 928

Note:
1. If the reader process is reading, then no writer process should write.
2. If any writer thread is writing, then reader process can not read as the source file(as you mentioned) is busy.

So, there should be just one synchronization variable(say sem_id) which should be used by both- reader process as well as writer process. Also, all the writer threads should use this variable to avoid overwriting.

writer process:

 writer_thread1 
  {
   writer_lock(sem_id);
     write the data
   release_writer_lock(sem_id);
  }
 writer_thread2 
  {
   writer_lock(sem_id);
     write the data
   release_writer_lock(sem_id);
  }

reader process

  reader 
  {
   reader_lock(sem_id);
     read the data
   release_reader_lock(sem_id);
  }

EDIT:
I am sorry to ignore the message slot limit. But I suggested this solution thinking that you are using a shared file(in which you are writing to and reading from) as you mentioned that in your question. Also, your question mentioned that it has several writer threads, though it is very clear that its not possible to write to a shared location simultaneously.
If there is just one message slot, then it can only be done as mentioned by @caf. But then, I think there is no use of using multiple writer threads because any writer thread can only write data when reader process has read it.

Upvotes: 0

caf
caf

Reputation: 239041

You'll need to use a pair of semaphores - one to block the reader until a writer has created something to read, and one to block the writers until the reader has read the existing messages.

Initialise the read semaphore to 0 and the write sempahore to 1. The reader does:

sem_wait(&read_sem);
/* Read and remove message */
sem_post(&write_sem);

The writers do:

sem_wait(&write_sem);
/* Write message */
sem_post(&read_sem);

Upvotes: 1

Related Questions