ringbuffer原理_git stash pop冲突

ringbuffer原理_git stash pop冲突例子:ringbuffer.c实现#include<stdlib.h>#include<stdio.h>#include<string.h>#include”ringbuffer.h”voidringbuffer_init(structringbuffer*rb,uint8_t*pool,int16_tsize){if(rb==NULL){return;}rb-&g

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

例子:

ringbuffer.c实现

#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

#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

#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中的锁保护去掉后:

ringbuffer原理_git stash pop冲突执行出错:

ringbuffer原理_git stash pop冲突

用GDB观察一下:

ringbuffer原理_git stash pop冲突

length竟然是负值.

ringbuffer原理_git stash pop冲突

所以源头是:

ringbuffer原理_git stash pop冲突

ringbuffer原理_git stash pop冲突

ringbuffer原理_git stash pop冲突

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

ringbuffer原理_git stash pop冲突

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

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

ringbuffer原理_git stash pop冲突

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


结束!

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

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

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ModelAndView 配置与使用「建议收藏」

    ModelAndView 配置与使用「建议收藏」一,ModelAndView介绍:1)ModelAndView用于后台与前端页面交互;2)可以用于重定向与转发到指定页面,3)可以保存数据然后渲染到页面二,使用:1)在Controlle

    2022年7月1日
  • 手把手教你搭建第一个Spring Batch项目

    手把手教你搭建第一个Spring Batch项目写在前面:我是「沸羊羊_」,昵称来自于姓名的缩写fyy,之前呕心沥血经营的博客因手残意外注销,现经营此账号。本人是个小菜,正向着全栈工程师的方向努力着,文章可能并不高产,也很基础,但每写一篇都在用心总结,请大佬勿喷。如果您对编程有兴趣,请关注我的动态,一起学习研究。感谢每位读者!文章目录一、概述二、实例1、新建springboot项目2、springboot项目配置一、概述SpringBatch是一个轻量级,全面的批处理框架。一个典型的批处理过程可能是:从数据库,文件或.

    2022年5月8日
  • jquery 默认隐藏div,点击按钮显示,再次点击隐藏

    jquery 默认隐藏div,点击按钮显示,再次点击隐藏

    2021年7月15日
  • two bin system_system系统目录是什么

    two bin system_system系统目录是什么这个里面主要存放的是常规下载的应用程序,可以看到都是以APK格式结尾的文件, 在这个文件夹下的程序为系统默认的组件,自己安装的软件将不会出现在这里,而是\data\文件夹中。\system\app\AlarmClock.apk 闹钟\system\app\AlarmClock.odex\system\app\Browser.apk 浏览器\system\app\Browser.

    2022年10月10日
  • MATLAB GUI表格(uitable)的增删操作

    MATLAB GUI表格(uitable)的增删操作这几天,查看了很多的MATLABGUI表格的操作,发现都没有一个完整的增删改的帖子。于是在我自己摸索下,自己搞出来了,增删操作。接下来就分享给大家!界面布局:表格的tag:uitable1添加电价的tag:addEle删除电价的tag:delEle 首先建立一个newData.mat,用于存放表格数据: 在打开窗体的时候,加载newData.mat文件,…

    2022年6月3日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号