C:使用单独文件中的函数

时间:2015-03-19 07:02:37

标签: c linux synchronization pthreads

尝试使用我编码的单独文件中的有界缓冲区,似乎这就是代码疯狂的地方。相当新的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)

1 个答案:

答案 0 :(得分:1)

bbuff_blocking_extract()

out = out % QUEUE_SIZE;

应该是:

out = (out+1) % QUEUE_SIZE;