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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 智能优化算法总结

    智能优化算法总结优化算法有很多,经典算法包括:有线性规划,动态规划等;改进型局部搜索算法包括爬山法,最速下降法等,模拟退火、遗传算法以及禁忌搜索称作指导性搜索法。而神经网络,混沌搜索则属于系统动态演化方法。梯度为基础的传统优化算法具有较高的计算效率、较强的可靠性、比较成熟等优点,是一类最重要的、应用最广泛的优化算法。但是,传统的最优化方法在应用于复杂、困难的优化问题时有较大的局限性。一个优化问题称为是复杂的,通常是

    2022年5月24日
    36
  • 【超详细】手把手教你ElasticSearch集群搭建

    【超详细】手把手教你ElasticSearch集群搭建1.ElasticSearch快速入门1.1.基本介绍ElasticSearch特色Elasticsearch是实时的分布式搜索分析引擎,内部使用Lucene做索引与搜索实时性:新增到ES中的数据在1秒后就可以被检索到,这种新增数据对搜索的可见性称为“准实时搜索”分布式:意味着可以动态调整集群规模,弹性扩容集群规模:可以扩展到上百台服务器,处理PB级结构化或非结构化数据各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作Lucene是Ja

    2022年10月13日
    4
  • STM32驱动1602A 8086协议[通俗易懂]

    STM32驱动1602A 8086协议[通俗易懂]本来想学I2C发现1602上没有I2C的接口,他是8086并口的就先把它搞了//1602的外设文件#include“lcd1602.h”#include“sys.h”#include“delay.h”#include“stdio.h”voidGPIO_Configuration(void){GPIO_InitTypeDefGPIO_InitStructure;R…

    2022年9月22日
    2
  • VS Code折腾记 – (2) 快捷键大全,没有更全

    VS Code折腾记 – (2) 快捷键大全,没有更全前言VSCode的快捷键继承了一些IDE风格,有VS的身影,也有Emacs的身影。。简言之,内置快捷键玩熟了,效率提高不是一点两点。VsCode快捷键有五种组合方式(科普)Ctrl+Shift+?:这种常规组合按钮Ctrl+VCtrl+V:同时依赖一个按键的组合Shift+Vc:先组合后单键的输入Ctrl+Click:键盘+鼠标点击Ctrl+

    2022年6月16日
    37
  • 通过bindservice方法开启的服务,通过什么方法解绑_controller调用多个service

    通过bindservice方法开启的服务,通过什么方法解绑_controller调用多个service绑定本地服务AndroidManifest.xml中声明服务:&lt;serviceandroid:name=".TestLocalService"&gt;&lt;intent-filter&gt;&lt;actionandroid:name="maureen.intent.action.BIND_LOCAL…

    2022年9月18日
    2
  • SOP 1.1.0 发布,开放平台解决方案项目「建议收藏」

    SOP 1.1.0 发布,开放平台解决方案项目「建议收藏」SOP 1.1.0 发布,开放平台解决方案项目

    2022年4月21日
    46

发表回复

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

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