尝试使用我编码的单独文件中的有界缓冲区,似乎这就是代码疯狂的地方。相当新的C,我想知道我是否正确使用缓冲区。实例化的概念不在这里,所以如果我只调用bbuff_blocking_insert
之类的函数之一,那么数组会被初始化吗?如何进行适当的调用以使其正常工作?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
输出
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
答案 0 :(得分:1)
在bbuff_blocking_extract()
,
out = out % QUEUE_SIZE;
应该是:
out = (out+1) % QUEUE_SIZE;