首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >ringbuffer原理_git stash pop冲突

ringbuffer原理_git stash pop冲突

作者头像
全栈程序员站长
发布2022-10-03 13:13:31
发布2022-10-03 13:13:31
8770
举报

大家好,又见面了,我是你们的朋友全栈君。

例子:

ringbuffer.c实现

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ringbuffer.h"
void ringbuffer_init(struct ringbuffer *rb, uint8_t *pool, int16_t size)
{
if(rb == NULL)
{
return;
}
rb->read_mirror = rb->read_index = 0;
rb->write_mirror = rb->write_index = 0;
rb->buffer_ptr = pool;
rb->buffer_size = size;
pthread_mutex_init(&rb->mutex_lock,NULL);
return;
}
void ringbuffer_reset(struct ringbuffer *rb)
{
if(rb == NULL)
{
return;
}
rb->read_mirror = 0;
rb->read_index = 0;
rb->write_mirror = 0;
rb->write_index = 0;
return;
}
int16_t ringbuffer_put(struct ringbuffer *rb, const uint8_t *ptr, int16_t length)
{
if(rb == NULL || length == 0)
{
return 0;
}
int16_t size; 
pthread_mutex_lock(&rb->mutex_lock);
size = ringbuffer_space_len(rb);
pthread_mutex_unlock(&rb->mutex_lock);
if(size == 0)
return 0;
if (size < length)
{
length = size;
}
if (rb->buffer_size - rb->write_index > length)
{
memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
rb->write_index += length; 
return length;
}
memcpy(&rb->buffer_ptr[rb->write_index],&ptr[0],rb->buffer_size - rb->write_index);
memcpy(&rb->buffer_ptr[0],&ptr[rb->buffer_size - rb->write_index],length - (rb->buffer_size - rb->write_index));
pthread_mutex_lock(&rb->mutex_lock);
rb->write_mirror = ~rb->write_mirror;
rb->write_index = length - (rb->buffer_size - rb->write_index);
pthread_mutex_unlock(&rb->mutex_lock);
return length;
}
int16_t ringbuffer_get(struct ringbuffer *rb, uint8_t *ptr, int16_t length)
{
if(rb == NULL || length == 0)
{
return 0;
}
int16_t size; 
pthread_mutex_lock(&rb->mutex_lock);
size = ringbuffer_data_len(rb);
pthread_mutex_unlock(&rb->mutex_lock);
if (size == 0) return 0;
if (size < length)
{
length = size;
}
if (rb->buffer_size - rb->read_index > length)
{
memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
rb->read_index += length;
return length;
}
memcpy(&ptr[0],&rb->buffer_ptr[rb->read_index],rb->buffer_size - rb->read_index);
memcpy(&ptr[rb->buffer_size - rb->read_index], &rb->buffer_ptr[0], length - (rb->buffer_size - rb->read_index));
pthread_mutex_lock(&rb->mutex_lock);
rb->read_mirror = ~rb->read_mirror; 
rb->read_index = length - (rb->buffer_size - rb->read_index);
pthread_mutex_unlock(&rb->mutex_lock);
return length;
}
enum ringbuffer_state ringbuffer_status(struct ringbuffer *rb) 
{
if (rb->read_index == rb->write_index)
{
if (rb->read_mirror == rb->write_mirror)
{
return RINGBUFFER_EMPTY;
}
else
{
return RINGBUFFER_FULL;
}
}
return RINGBUFFER_HALFFULL;
}
int16_t ringbuffer_data_len(struct ringbuffer *rb)
{
switch (ringbuffer_status(rb)) 
{
case RINGBUFFER_EMPTY:
return 0;
case RINGBUFFER_FULL:
return rb->buffer_size; 
case RINGBUFFER_HALFFULL:
default:
if (rb->write_index > rb->read_index)
return rb->write_index - rb->read_index;
else
return rb->buffer_size - (rb->read_index - rb->write_index); 
}
}

ringbuffer.h

代码语言:javascript
复制
#ifndef __RING_BUFFER__
#define __RING_BUFFER__
#include <stdint.h>
#include <stddef.h>
#include <pthread.h>
#include <unistd.h>
struct ringbuffer
{
uint8_t *buffer_ptr;
uint16_t read_mirror : 1;
uint16_t read_index : 15;
uint16_t write_mirror : 1;
uint16_t write_index : 15;
int16_t buffer_size;
pthread_mutex_t mutex_lock;
};
enum ringbuffer_state
{
RINGBUFFER_EMPTY,
RINGBUFFER_FULL,
RINGBUFFER_HALFFULL,
RINGBUFFER_INVALID,
};
void ringbuffer_init(struct ringbuffer *rb, uint8_t *pool, int16_t size);
void ringbuffer_reset(struct ringbuffer *rb);
int16_t ringbuffer_put(struct ringbuffer *rb, const uint8_t *ptr, int16_t length);
int16_t ringbuffer_get(struct ringbuffer *rb, uint8_t *ptr, int16_t length);
int16_t ringbuffer_data_len(struct ringbuffer *rb);
struct ringbuffer* ringbuffer_create(int16_t length);
void ringbuffer_destroy(struct ringbuffer *rb);
static inline int16_t ringbuffer_get_size(struct ringbuffer *rb)
{
return rb->buffer_size;    
}
#define ringbuffer_space_len(rb) ((rb)->buffer_size - ringbuffer_data_len(rb))
#endif

main.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include "ringbuffer.h"
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
struct ringbuffer *rb;
void *writer_thread(void *args)
{
uint8_t w = 0;
while(1)
{
/*pthread_mutex_lock(&mutex);*/
if(ringbuffer_put(rb, &w, 1) == 1)
w ++;
/*pthread_mutex_unlock(&mutex);*/
}
return NULL;
}
void *reader_thread(void *args)
{
uint8_t r;
while(1)
{
/*pthread_mutex_lock(&mutex);*/
if (ringbuffer_get(rb, &r, 1) == 1)
printf("---%x---\n", r);
/*pthread_mutex_unlock(&mutex);*/
}
return NULL;
}
int main(void)
{
unsigned int rc;
#if 1
uint8_t *buffer = (uint8_t *)malloc(1024 + sizeof(struct ringbuffer) + 16);
if(buffer == NULL) return -1;
if((unsigned long)buffer & 7 != 0)
{
printf("%s line %d not aligned.\n", __func__, __LINE__);
return -1;
}
rb=(struct ringbuffer *)buffer;
if(rb == NULL) return -1;
ringbuffer_init(rb, buffer + sizeof(struct ringbuffer), 1024);
printf("buffer = %p, sizeof(rb) = %ld.\n", buffer, sizeof(struct ringbuffer));
#else
static struct ringbuffer rbb;
uint8_t *buffer = (uint8_t *)malloc(1024);
if(buffer == NULL) return -1;
rb = &rbb;
memset(rb, 0x00,sizeof(struct ringbuffer));
memset(buffer, 0x00,1024);
ringbuffer_init(rb, buffer, 1024);
#endif
pthread_t writer;
rc = pthread_create(&writer, NULL, writer_thread, NULL);
if (rc)
{
printf("ERROR; return code is %d\n", rc);
return EXIT_FAILURE;
}
pthread_t reader;
rc = pthread_create(&reader, NULL, reader_thread, NULL);
if (rc)
{
printf("ERROR; return code is %d\n", rc);
return EXIT_FAILURE;
}
pthread_join(reader, NULL);
pthread_join(writer, NULL);
return EXIT_SUCCESS;
}

运行无问题,但是当把ringbuffer.c中的锁保护去掉后:

执行出错:

用GDB观察一下:

length竟然是负值.

所以源头是:

测试并计算并非原子的,所以这里肯定有问题,需要加锁保护,比如下图

在判断的时候write > read, 比如147行,但是当计算的时候,由于write是独立的线程,它已经将write递增并回绕到56.而且read由于在本线程,仍然保留了706,所以已经不符合判断时候的逻辑write>read.

但是仍然按照错误的逻辑计算,所得得到了负值.

解决的办法就是将判断和计算上锁原子化.


结束!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197545.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月4日 上,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档