Reputation: 35
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
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
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