I have a thread which plays an mp3 using ao_lib in C. I need someway of skipping to the next mp3 halfway through playing, so after creating the thread which plays an mp3, I have tried to create another thread which would wait for a user to enter a character and if the first one joins before the second then the second is also killed.
main()
{
ret1 = pthread_create(&thread1, NULL, func_play, (void *) url);
ret2 = pthread_create(&thread2, NULL, func_char, NULL);
/* I need to somehow do something here to break func_play if a user
enters a specific char in func_char */
pthread_join(thread1, NULL);
pthread_cancel(thread2);
return 0;
}
That didn't work. Any solutions would be really welcome.
Thanks
This would be the pattern that I think would work, I don't know how the mp3 playing function works, but you need it to be non-blocking, perhaps read the .mp3 file and play it in chunks, so you can break the main loop (_the loop that plays the .mp3) using something like this
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
static pthread_mutex_t mutex;
struct SharedData
{
const char *url;
int stop;
int ready;
};
void *
mainloop(void *data)
{
struct SharedData *sharedData;
int ready;
int stop;
sharedData = data;
if (sharedData == NULL)
return NULL;
stop = 0;
ready = 0;
while (ready == 0)
{
pthread_mutex_lock(&mutex);
ready = sharedData->ready;
pthread_mutex_unlock(&mutex);
usleep(1000);
}
while (stop == 0)
{
pthread_mutex_lock(&mutex);
stop = sharedData->stop;
pthread_mutex_unlock(&mutex);
printf(".");
fflush(stdout);
sleep(1);
}
return NULL;
}
void *
controlthread(void *data)
{
int chr;
struct SharedData *sharedData;
sharedData = data;
if (sharedData == NULL)
return NULL;
pthread_mutex_lock(&mutex);
sharedData->ready = 1;
pthread_mutex_unlock(&mutex);
printf("Press return to stop the main loop...\n");
while (((chr = getchar()) != EOF) && (chr != '\n'))
usleep(1000);
pthread_mutex_lock(&mutex);
sharedData->stop = 1;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(void)
{
struct SharedData data;
pthread_t threads[2];
pthread_mutex_init(&mutex, NULL);
memset(&data, 0, sizeof(data));
pthread_create(&threads[0], NULL, mainloop, &data);
pthread_create(&threads[1], NULL, controlthread, &data);
pthread_join(threads[0], NULL);
return 0;
}
Related
My task is to make a game simulation that uses threads to simulate work. If the thread's been given command to do another work it should pause it's first work and start the new work. How to implement it in C? I've tried with separate function for the input and signaling a condition variable but when it enters the giveCommand() function it just waits for input.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
char command;
pthread_mutex_t mutex;
pthread_cond_t condVar;
void giveCommand()
{
scanf("%c", command);
pthread_cond_signal (&condVar);
return;
}
void *thread(void *N)
{
char c;
do
{
pthread_mutex_lock(&mutex);
//do its work
pthread_cond_timedwait(&condVar, &mutex, 500000);// if command hasn't been given, continue work
pthread_mutex_unlock(&mutex);
pthread_cond_init(&condVar, NULL);
while(giveCommand());
}
}
int main()
{
int i;
int error;
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condVar, NULL);
while(1)
{
for (i = 0; i < NUM_THREADS; i++)
{
error = pthread_create(&threads[i], NULL, simulateWorker, NULL);
if (error != 0) printf("Error creating thread!");
}
for (i = 0; i < NUM_THREADS; i++)
{
error = pthread_join(threads[i], NULL);
if (error != 0) printf("Error joining thread!");
}
pthread_mutexattr_destroy(&mutex);
}
return 0;
}
With the given shared buffer of size 24,
Here is the below solution, for single producer & consumer using counting semaphore,
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFERSIZE 24
void *producer(void *);
void *consumer(void *);
sem_t mutex; //Controls buffer access
sem_t fullBuffer; //Prevents underflow
sem_t emptyBuffer; // Prevents overflow
char buf[BUFFERSIZE] = {0}; //Shared resource
int main(int argc, char *argv[])
{
pthread_t thread1, thread2;
sem_init(&mutex, 0, 1);
sem_init(&fullBuffer, 0, 0);
sem_init(&emptyBuffer, 0, BUFFERSIZE);
int ret1, ret2;
ret1 = pthread_create(&thread1, NULL, producer, (void *)0);
ret2 = pthread_create(&thread2, NULL, consumer, (void *)0);
printf("Main function after pthread create\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
sem_destroy(&mutex);
sem_destroy(&fullBuffer);
sem_destroy(&emptyBuffer);
return 0;
}
void *producer(void *index)
{
int * startIndex = index;
int currentProduceIndex = *startIndex;
while(1) {
sem_wait(&emptyBuffer); // Prevents overflow, when value is 0
sem_wait(&mutex); // Controls buffer access
buf[currentProduceIndex] = currentProduceIndex;
sem_post(&mutex);
sem_post(&fullBuffer);
currentProduceIndex = (currentProduceIndex+1) % BUFFERSIZE;
}
}
void *consumer(void *index)
{
int *startIndex = index;
int currentConsumeIndex = *startIndex;
while(1) {
sem_wait(&fullBuffer); // Prevents underflow, when value is 0
sem_wait(&mutex);
printf("Consumed %d: ", buf[currentConsumeIndex]);
sem_post(&mutex);
sem_post(&emptyBuffer);
currentConsumeIndex = (currentConsumeIndex+1) % BUFFERSIZE;
}
}
Above code has single producer and consumer on buf, using 3 semaphores mutex, fullBuffer & emptyBuffer.
To add further, Does 3 semaphore, mutex, fullBuffer & emptyBuffer suffice to introduce multiple producers and consumers to access buf, in the above code?
As seibie pointed out, it is hard to implement using semaphores. I have modified code and used two mutex and two cond variables. You can create multiple producer and consumer threads and it should work fine.
#include <stdio.h>
#include <pthread.h>
#define BUFFERSIZE 24
void *producer(void *);
void *consumer(void *);
pthread_mutex_t consMutex;
pthread_mutex_t prodMutex;
pthread_cond_t consCond;
pthread_cond_t prodCond;
// Shared resource: Using it to store flags.
// If value at index is 0, it means the index is free
// and producer can write data. If it is 1, it means
// that index is filled, consumer can consume it.
// You need use separate array for actual data.
char buf[BUFFERSIZE] = {0};
int main(void)
{
pthread_t thread1, thread2;
pthread_mutex_init(&consMutex, NULL);
pthread_mutex_init(&prodMutex, NULL);
pthread_cond_init(&consCond, NULL);
pthread_cond_init(&prodCond, NULL);
int ret1, ret2;
int prodIndex = 0;
int consIndex = 0;
ret1 = pthread_create(&thread1, NULL, producer, (void *)&prodIndex);
ret2 = pthread_create(&thread2, NULL, consumer, (void *)&consIndex);
printf("Main function after pthread create\n");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&prodMutex);
pthread_mutex_destroy(&consMutex);
pthread_cond_destroy(&prodCond);
pthread_cond_destroy(&consCond);
return 0;
}
void *producer(void *index)
{
int *currentProduceIndex = index;
while(1) {
pthread_mutex_lock(&prodMutex);
/* Check if current index is free to fill. */
while(1 == buf[*currentProduceIndex])
{
/* If index is not free, wait for consumer to consume. */
pthread_cond_wait(&prodCond, &prodMutex);
}
/* Now the current index is free. Fill it. */
buf[*currentProduceIndex] = 1;
/* Update the producer index. */
*currentProduceIndex = (*currentProduceIndex+1)%BUFFERSIZE;
pthread_mutex_unlock(&prodMutex);
/* Notify consumer that an item has been produced. */
pthread_mutex_lock(&consMutex);
pthread_cond_signal(&consCond);
pthread_mutex_unlock(&consMutex);
}
return NULL;
}
void *consumer(void *index)
{
int *currentConsumeIndex = index;
while(1) {
pthread_mutex_lock(&consMutex);
/* Check if current index is empty. */
while(0 == buf[*currentConsumeIndex])
{
/* If index is empty, wait for producer to produce. */
pthread_cond_wait(&consCond, &consMutex);
}
/* Index is filled, consume it. */
buf[*currentConsumeIndex] = 0;
/* Update the consumer index. */
*currentConsumeIndex = (*currentConsumeIndex+1)%BUFFERSIZE;
pthread_mutex_unlock(&consMutex);
/* Notify producer that an item has been consumed. */
pthread_mutex_lock(&prodMutex);
pthread_cond_signal(&prodCond);
pthread_mutex_unlock(&prodMutex);
}
return NULL;
}
Working on the Producer and Consumer problem for a class and having trouble just putting on the final touches. The problem I am encountering is that i think my mutex locks are not locking my threads out of the function. For example if I run the program and pass it the parameters 2 4 4 7 it would print 8 7's and then 2 seconds later it will print 8 8's and then 8 9's and so on. I have tried using trylock and moving around the semaphores but to no avail. Is there something that I am missing when that is causing none of the threads to be locked out?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
typedef int buffer_item;
#define BUFFER_SIZE 5
#define TRUE 1
buffer_item START_NUMBER;
int counter;
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
buffer_item buffer[BUFFER_SIZE];
void* producer(void *ptr);
void* consumer(void *ptr);
pthread_cond_t condc, condp;
pthread_mutex_t mutex;
int sleepTime, producerThreads, consumerThreads,a;
pthread_attr_t attr;
sem_t full, empty;
int insert_item(buffer_item item)
{
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1;
}
}
int remove_item(buffer_item *item)
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else {
return -1;
}
}
void* producer(void *ptr) {
buffer_item item;
item = START_NUMBER;
while(TRUE) {
sleep(sleepTime);
sem_wait(&empty);
pthread_mutex_lock(&mutex);
if(insert_item(item)) {
fprintf(stderr, "error \n");
}
else {
printf("producer%u produced %d\n", (unsigned int)pthread_self(),item);
item++;
}
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void* consumer(void *ptr) {
buffer_item item;
while(TRUE) {
sleep(sleepTime);
sem_wait(&full);
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "error \n");
}
else {
printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),item);
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
void initializeData() {
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main(int argc, char **argv) {
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
START_NUMBER = atoi(argv[4]);
initializeData();
pthread_t pro, con;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condc, NULL);
pthread_cond_init(&condp, NULL);
for(a=0; a< consumerThreads;a++)
pthread_create(&con, NULL, consumer, NULL);
for(a=0;a<producerThreads;a++)
pthread_create(&pro, NULL, producer, NULL);
pthread_join(con, NULL);
pthread_join(pro, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
sleep(sleepTime);
}
Thanks for the help Dmitri, after moving around the lines you told me about and some discussion with one of my friends I finally got it to start outputting the right numbers!
This is the output i have been looking for
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
typedef int buffer_item;
#define BUFFER_SIZE 5
#define TRUE 1
buffer_item START_NUMBER;
buffer_item item;
int counter;
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
buffer_item buffer[BUFFER_SIZE];
void* producer(void *ptr);
void* consumer(void *ptr);
pthread_cond_t condc, condp;
pthread_mutex_t mutex;
int sleepTime, producerThreads, consumerThreads, a, item;
pthread_attr_t attr;
sem_t full, empty;
int insert_item(buffer_item item)
{
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1;
}
}
int remove_item(buffer_item *item)
{
if(counter > 0) {
*item = buffer[(counter-1)];
printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),buffer[counter-1]);
counter--;
return 0;
}
else {
return -1;
}
}
void* producer(void *ptr) {
while(TRUE) {
sleep(sleepTime);
sem_wait(&empty);
pthread_mutex_lock(&mutex);
if(insert_item(START_NUMBER)) {
fprintf(stderr, "error \n");
}
else {
printf("producer%u produced %d\n", (unsigned int)pthread_self(),START_NUMBER);
START_NUMBER++;
}
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void* consumer(void *ptr) {
while(TRUE) {
sleep(sleepTime);
sem_wait(&full);
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "error \n");
}
else {
// printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),&START_NUMBER);
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
void initializeData() {
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main(int argc, char **argv) {
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
START_NUMBER = atoi(argv[4]);
item = START_NUMBER;
initializeData();
pthread_t pro, con;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condc, NULL);
pthread_cond_init(&condp, NULL);
for(a=0; a< consumerThreads;a++)
pthread_create(&con, NULL, consumer, NULL);
for(a=0;a<producerThreads;a++)
pthread_create(&pro, NULL, producer, NULL);
pthread_join(con, NULL);
pthread_join(pro, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
sleep(sleepTime);
}
I want to create two thread which output interleave like below
Thread1:1=>Ping!
Thread2:2=>Pong!
Thread1:3=>Ping!
Thread1:4=>Ping!
Thread2:5=>Pong!
Thread2:6=>Pong!
Thread1:7=>Ping!
Thread2:8=>Pong!
Thread1:9=>Ping!
..........
until 50
and my code is below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i){
//create thread
res1 = pthread_create(&thread1, NULL, increment1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread1, NULL);
res2 = pthread_create(&thread2, NULL, increment2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread2, NULL);
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread1:%d\nPing!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
void* increment2(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread2:%d\nPong!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
But I think that what I do isn't using two thread in parallel and is wrong, what I use is sequential alternative executing two thread and it isn't not in parallel.(By using pthread_join, thread2 will execute after thread1 finish).
I try to using semaphore it seem that it cannot assure the thread execution order.
What I want to ask is
1.how to using semaphore to assure the two thread order?
2.how to pause the thread and resume it? I think that I do is create new two pthread in a loop cycle.
Thank in advance.
Add a second semaphore and initialize it to zero so that thread1 is forced to first. Then increment1 and increment2 keep signally that it is the other threads turn to go. You had some minor hangups with where joined things that you can figure out.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;
int main()
{
pthread_t thread[2];
int res = 0;
int number = 0;
int i = 0;
if (sem_init(&sem1, 0, 1) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem2, 0, 0) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i)
{
res = pthread_create(&thread[0], NULL, increment1, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
res = pthread_create(&thread[1], NULL, increment2, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
for (int j = 0; j < 2; ++j)
{
pthread_join(thread[j], NULL);
}
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg)
{
sem_wait(&sem1);
count ++;
printf("Thread1:%d Ping!\n", count);
fsync(fileno(stdout));
sem_post(&sem2);
}
void* increment2(void* arg)
{
sem_wait(&sem2);
count ++;
printf("Thread2:%d Pong!\n", count);
fsync(fileno(stdout));
sem_post(&sem1);
}
Thank for you guys, I have modified it and it seems fine.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&c_sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_1, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_2, 0, 0) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
//create thread
res1 = pthread_create(&thread1, NULL, increment_1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
res2 = pthread_create(&thread2, NULL, increment_2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) {
while(1){
sem_wait(&sem_1);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_2);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread1:%d->Ping!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_2);
}
}
void* increment_2(void* arg) {
while(1){
sem_wait(&sem_2);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_1);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread2:%d->Pong!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_1);
}
}
What I want to accomplish:
In the main function are created two threads. They increment a global variable with the number 5. And send a signal to consumer thread that decrements the variables.In the consumer thread between each decrementation the current value is displayed. The main thread has to wait until all the threads are finished and then exit.
What I get:
Some times the main function exits before the consumer had a chance to display the results. I'm using pthread_join, but it returns error code 3.
Any Ideas how to get the wanted results?
The code is bellow.
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
static pthread_mutex_t mtx;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *producer(void *arg);
void *consumer(void *arg);
static int avail = 0;
int main(int argc, char *argv[]){
pthread_t cons1, prod1, prod2;
int status;
int t1;
int t2;
int t3;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_mutexattr_t mtxAttr;
pthread_mutexattr_settype(&mtxAttr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mtx, &mtxAttr);
t1 = pthread_create(&prod1, &attr, producer, NULL);
if(t1 != 0){
perror("problem1");
}
t2 = pthread_create(&prod2, &attr, producer, NULL);
if(t2 != 0){
perror("problem2");
}
t3 = pthread_create(&cons1, &attr, consumer, NULL);
if(t3 != 0){
perror("problem3");
}
status = pthread_join(t1, NULL);
if(status != 0){
perror("can't join1");
}
status = pthread_join(t2, NULL);
if(status != 0){
perror("can't join2");
printf("\n%d\n", status);
}
status = pthread_join(t3, NULL);
if(status != 0){
printf("%s",strerror(errno));
}
printf("\nend result \t%d\n",avail);
printf("fin\n");
//while(1){}
return 0;
}
void *producer(void *arg){
int s;
printf("producer\n");
s = pthread_mutex_lock(&mtx);
avail+=5;
s = pthread_mutex_unlock(&mtx);
s = pthread_cond_signal(&cond);
pthread_exit(NULL);
}
void *consumer(void *arg){
int s;
while(1) {
s = pthread_mutex_lock(&mtx);
if(s !=0 ){
perror("lock err");
}
while (avail == 0) {
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) {
avail--;
printf("Temp: %d \n",avail);
}
s = pthread_mutex_unlock(&mtx);
}
printf("done");
pthread_exit(NULL);
}
Don't join on t1, t2 or t3. Those are the return codes of the pthread_create() function. Use pthread_join() on prod1, prod2 and cons1 instead. And please compile with -Wall -Wextra.