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冲突

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


结束!

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 赛门铁克卸载工具CleanWipe14亲测有效

    赛门铁克卸载工具CleanWipe14亲测有效卸载烦人的赛门铁克,把我恶心坏了,不过最后卸载了。找了很多方法,都很麻烦,自己试了试也没成功。。。然后找到了一个CleanWipe14的卸载工具网盘,然后成功卸载!!!网盘链接:https://pan.baidu.com/s/13nOA83ngCaxLN4h627-oyQ提取码:dkck原文:https://www.52pojie.cn/thread-1071900-1-1.html…

  • 详解RocketMQ不同类型的消费者

    详解RocketMQ不同类型的消费者

  • sql语句 异常 Err] 1064 – You have an error in your SQL syntax; check the manual that corresponds to your

    sql语句 异常 Err] 1064 – You have an error in your SQL syntax; check the manual that corresponds to your在我们开发的工程中,有时候会报[Err]1064-YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtousenear——这种异常不用多想,肯定是我们的sql语句出现问题,下面…

  • c语言爱心代码

    c语言爱心代码#include<stdio.h>intmain(){inti,j,k,l,m;charc=3;//ASCII码里面3就是一个字符小爱心for(i=1;i<=5;i++)printf(“\n”);//开头空出5行for(i=1;i<=3;i++){//前3行中间有空隙分开来写for(j=1;j<=32-2*i;j++)printf(“”);//左边的空格,每下一行左边的空格比上一行少2个//8*n.

  • web安全概述_网络安全和web安全

    web安全概述_网络安全和web安全域名什么是域名?域名(DomainName),又称网域,是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)。例:www.baidu.comDNS什么是DNS?域名系统(DomainNameSystem,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过2

  • CNN经典模型汇总[通俗易懂]

    CNN经典模型汇总[通俗易懂]本文主要对CNN领域的经典模型进行汇总,算是对近期的学习做一个小总结。基础知识作为深度学习的基础,神经网络这个算法是必须要有深入的了解的,这里不介绍太多,简单介绍一下原理和单个神经元的结构:一、BP神经网络的概念BP神经网络是一种多层的前馈神经网络,其主要的特点是:信号是前向传播的,而误差是反向传播的。具体来说,对于如下的只含一个隐层的神经网络模型:BP神经网络的过程主要分为两个阶段,第一阶段是信号

发表回复

您的电子邮箱地址不会被公开。

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