Paste #26877

typedef struct {

	// This shouldn't really be here but I'm too lazy to make another struct
	// It's for signaling the generators that they should stop generating
	int please_exit;

	char offset_read;
	char offset_write;

	sem_t sem_read;
	sem_t sem_write;
	sem_t sem_lock;

	size_t size;
	size_t free_space;
	size_t used_space;

	char data[];

} circular_buffer;


circular_buffer* make_circular_buffer(size_t size, char* file){

	char protection = PROT_READ | PROT_WRITE;
	char visibility;
	int fd;

	if(file == NULL){

    	visibility = MAP_ANONYMOUS | MAP_SHARED;
    	fd = 0;

    } else {

    	visibility = MAP_SHARED;
    	fd = open(file, O_CREAT | O_RDWR);
    	ftruncate(fd, sizeof(circular_buffer) + size);

    	if(fd < 0){
    		fprintf(stderr, "make_circular_buffer: opening file failed.\n");
    		exit(10);
    	}

    }

    circular_buffer* b = mmap(
    	NULL,
    	sizeof(circular_buffer) + size,
    	protection, visibility, fd, 0
    );

    if(b == MAP_FAILED) {
    	fprintf(stderr, "make_circular_buffer: mmap error.\n");
    	exit(11);
    }

    if(file != NULL){
    	close(fd);
    }

    b->please_exit = 0;
    b->offset_read = 0;
    b->offset_write = 0;
    b->size = size;
    b->data = (char*)(b) + sizeof(circular_buffer);

    b->free_space = size;
    b->used_space = 0;

    return b;

}