linux c 字符串环形buf (二)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <pthread.h>

#include <sys/types.h>

#include <unistd.h>

int debug = 1;

pthread_mutex_t prod_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t prod_cond = PTHREAD_COND_INITIALIZER;

pthread_mutex_t cons_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cons_cond = PTHREAD_COND_INITIALIZER;

// Define the ring buffer structure

typedef struct {

char *buffer;

size_t capacity;

size_t read_pos;

size_t write_pos;

char full;

char empty;

pthread_mutex_t lock;

} StringRingBuffer;

StringRingBuffer rb;

// Initialize the ring buffer

void init_string_ring_buffer(StringRingBuffer *rb, size_t capacity) {

rb->buffer = malloc(capacity);

if (rb->buffer == NULL) {

perror("malloc");

exit(EXIT_FAILURE);

}

rb->capacity = capacity;

rb->read_pos = 0;

rb->write_pos = 0;

rb->full = 0;

rb->empty = 1;

pthread_mutex_init(&rb->lock, NULL);

}

// Destructor for the ring buffer

void destroy_string_ring_buffer(StringRingBuffer *rb) {

free(rb->buffer);

pthread_mutex_destroy(&rb->lock);

}

// Write data to the ring buffer

ssize_t write_to_string_ring_buffer(StringRingBuffer *rb, const char *data, size_t len)

{

ssize_t written = 0;

size_t write_pos;

size_t read_pos;

size_t space_before_wrap;

size_t available_space;

if (len == 0)

return -1;

pthread_mutex_lock(&rb->lock);

if (rb->full == 1)

{

//is full

goto write_end;

}

//printf("==> write_to_string\n");

write_pos = rb->write_pos;

read_pos = rb->read_pos;

if (write_pos < read_pos)

{

available_space = read_pos - write_pos;

// real len

len = len < available_space ? len : available_space;

memcpy(rb->buffer + write_pos, data, len);

rb->write_pos += len;

written = len;

}

else if (write_pos >= read_pos)

{

available_space = rb->capacity - (write_pos - read_pos);

// real len

len = len < available_space ? len : available_space;

space_before_wrap = rb->capacity - write_pos;

if (len <= space_before_wrap)

{

memcpy(rb->buffer + write_pos, data, len);

rb->write_pos += len;

if(rb->write_pos > rb->capacity)

{

printf("error: in write:%lu rb->write_pos > rb->capacity =======================================\n", rb->write_pos );

exit(-1);

}

if (rb->write_pos >= rb->capacity) {

rb->write_pos = 0;

}

written = len;

}

else

{

// Wrap around

memcpy(rb->buffer + write_pos, data, space_before_wrap);

memcpy(rb->buffer, data + space_before_wrap, len - space_before_wrap);

rb->write_pos = len - space_before_wrap;

written = len;

}

}

if(debug)

printf("[%lu]Wrote %ld bytes, write_pos:%ld read_pos:%ld\n", pthread_self() , written, rb->write_pos, rb->read_pos);

if (rb->write_pos == rb->read_pos)

{

rb->full = 1;

if(debug)

printf("[%lu]full write_pos:%ld-%ld read_pos:%ld-%ld\n", pthread_self() , rb->write_pos,write_pos, rb->read_pos,read_pos);

}

//printf("<== write_to_string\n");

write_end:

rb->empty = 0;

pthread_mutex_unlock(&rb->lock);

return written;

}

// Read data from the ring buffer

ssize_t read_from_string_ring_buffer(StringRingBuffer *rb, char *dest, size_t len)

{

ssize_t read_len = 0;

size_t write_pos;

size_t read_pos;

size_t data_before_wrap;

//size_t data_after_wrap;

size_t available_data;

if (len == 0)

return -1;

pthread_mutex_lock(&rb->lock);

if (rb->empty == 1)

{

goto read_end;

}

//printf("==> read_from_string\n");

write_pos = rb->write_pos;

read_pos = rb->read_pos;

if (write_pos <= read_pos)

{

available_data = rb->capacity - (read_pos - write_pos);

if (len > available_data)

{

//not enough

goto read_end;

}

data_before_wrap = rb->capacity - read_pos;

if (len <= data_before_wrap)

{

memcpy(dest, rb->buffer + read_pos, len);

rb->read_pos += len;

if(rb->read_pos > rb->capacity)

{

printf("error: in read:%lu rb->read_pos > rb->capacity =======================================\n", rb->read_pos);

exit(-1);

}

if (rb->read_pos >= rb->capacity) {

rb->read_pos = 0;

}

read_len = len;

}

else

{

memcpy(dest, rb->buffer + read_pos, data_before_wrap);

memcpy(dest + data_before_wrap, rb->buffer, len - data_before_wrap);

rb->read_pos = len - data_before_wrap;

read_len = len;

}

}

else if (write_pos > read_pos)

{

available_data = write_pos - read_pos;

if (len > available_data)

{

//not enough

goto read_end;

}

memcpy(dest, rb->buffer + read_pos, len);

rb->read_pos += len;

read_len = len;

}

if(debug)

printf("[%lu]Read %ld bytes: '%s', write_pos:%ld read_pos:%ld\n", pthread_self() , read_len, dest, rb->write_pos, rb->read_pos);

if (rb->write_pos == rb->read_pos)

{

rb->empty = 1;

if(debug)

printf("[%lu]empty write_pos:%ld-%ld read_pos:%ld-%ld\n", pthread_self(), rb->write_pos, write_pos, rb->read_pos, read_pos);

}

//printf("<== read_from_string\n");

read_end:

rb->full = 0;

pthread_mutex_unlock(&rb->lock);

return read_len;

}

void *func_producer(void *arg)

{

arg = arg;

struct timespec tv;

// Write some data

ssize_t written;

char test_str[] = "0123456789";

tv.tv_sec = 1;

while(1)

{

pthread_mutex_lock(&prod_mutex);

pthread_cond_timedwait(&prod_cond, &prod_mutex, &tv);

//pthread_cond_wait(&prod_cond, &prod_mutex);

//sleep(1);

while (1)

{

written = write_to_string_ring_buffer(&rb, test_str, strlen(test_str));

if(written <= 0)

{

//pthread_cond_signal(&cons_cond);

pthread_cond_broadcast(&cons_cond);

break;

}

//printf("Wrote %ld bytes\n", written);

}

pthread_mutex_unlock(&prod_mutex);

}

return NULL;

}

void *func_consumer(void *arg)

{

arg = arg;

struct timespec tv;

// Read the data back

ssize_t read_len;

char read_buf[20];

tv.tv_sec = 1;

while(1)

{

//sleep(1);

pthread_mutex_lock(&cons_mutex);

pthread_cond_timedwait(&cons_cond, &cons_mutex, &tv);

//pthread_cond_wait(&cons_cond, &cons_mutex);

while(1)

{

memset(read_buf, 0, sizeof(read_buf));

read_len = read_from_string_ring_buffer(&rb, read_buf, 10);

if(read_len <=0)

{

//pthread_cond_signal(&prod_cond);

pthread_cond_broadcast(&prod_cond);

//sleep(1);

//printf("Read %ld bytes: '%s'\n", read_len, read_buf);

break;

}

//printf("Read %ld bytes: '%s' out\n", read_len, read_buf);

}

pthread_mutex_unlock(&cons_mutex);

}

return NULL;

}

//gcc -g -O0 -std=c99 -Wall -Wextra -pedantic -pthread test.c -o string_ring_buffer

// Example usage

int main() {

int i;

pthread_t t_prod[10];

pthread_t t_cons[10];

init_string_ring_buffer(&rb, 25); // Initialize the ring buffer with capacity 20

for(i=0; i<5; i++)

{

pthread_create(&t_prod[i], NULL, func_producer, NULL);

pthread_create(&t_cons[i], NULL, func_consumer, NULL);

}

// Clean up

destroy_string_ring_buffer(&rb);

for(i=0; i<5; i++)

{

pthread_join(t_prod[i], NULL);

pthread_join(t_cons[i], NULL);

}

return 0;

}

相关推荐
保持低旋律节奏3 分钟前
linux——调试
linux·运维·服务器
牛奶咖啡139 分钟前
Linux系统故障排查思路实践教程(下)
linux·运维·服务器·su命令切换用户问题解决·文件打开过多问题解决·linux网络故障问题解决·linux故障排查思路
程序员zgh23 分钟前
常用通信协议介绍(CAN、RS232、RS485、IIC、SPI、TCP/IP)
c语言·网络·c++
coder4_31 分钟前
Linux 数据同步全攻略:NFS 共享、inotify+rsync 与 sersync 实战指南
linux·rsync·文件共享·nfs·数据同步·inotify·实时备份
Lynnxiaowen1 小时前
今天我们继续学习kubernetes内容Helm
linux·学习·容器·kubernetes·云计算
weixin_521431121 小时前
Docker容器技术
运维·docker·容器
Bigan(安)1 小时前
【奶茶Beta专项】【LVGL9.4源码分析】08-theme主题管理
linux·c语言·mcu·arm·unix
Evan芙1 小时前
nginx+php部署walle,发布php站点
运维·nginx·php
小汐睡着了1 小时前
解决虚拟机VMware与宿主机网络不通的问题-error
linux·网络·redhat
xdxghy09211 小时前
mini centos7+k3s部署(镜像拉取解决版)
linux·运维·服务器·阿里云·运维开发