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年02月 wireshark系列-数据抓包分析之DHCP协议

    【愚公系列】2022年02月 wireshark系列-数据抓包分析之DHCP协议实验步骤一获取DHCP数据包在windows平台上获取DHCP数据包在windows平台上,可以使用两种简单的方法实现,其原理一样。(1)在cmd上,使用ipconfig命令来获取。执行完上述命令后,将释放当前使用的地址信息。重新获取地址信息,执行命令如下执行完上面的命令后,将重新获取地址信息。在获取地址时,将会经过上面讲述的DHCP的4个阶段。这样,我们就能获取到DHCP数据包了。(2)通过禁用和启用网卡获取DHCP数据包在windows平台上,也可以通过禁用和启用网卡获取DHCP数

    2022年5月23日
    39
  • Python机器学习实战&lt;一&gt;:环境的配置

    Python机器学习实战&lt;一&gt;:环境的配置

    2021年11月14日
    48
  • 您的个人资料来自新版GoogleChrome_google guice

    您的个人资料来自新版GoogleChrome_google guice   来源:德胜网    4月6日,据国外媒体报道,谷歌希望作出额外的确认Buzz用户都知道他们的隐私设置。    在过去的周一一天内,谷歌计划要求Buzz用户当他们登陆进入该服务时重新确认他们的隐私偏好。这样做是为了表明现有的用户相同的确认画面,Buzz自动关注自己的Gmail联络人隐私权反弹增长之后谷歌争取为新用户建立该服务。    目前,该系统“建议”关注联系

    2022年10月16日
    0
  • MySQL——MySQL 图形化管理工具的介绍[通俗易懂]

    MySQL——MySQL 图形化管理工具的介绍[通俗易懂]文章目录MySQL——MySQL图形化管理工具的介绍1、MySQLWorkbench2、Navicat3、SQLyog4、DBeaver5、DataGripMySQL——MySQL图形化管理工具的介绍MySQL图形化管理工具极大地方便了数据库的操作与管理,常用的图形化管理工具有:MysQLWorkbench、phpMyAdmin、NavicatPreminum、MySQLDumper、SQLyog、dbeaver、MysQLODBcConnector、DataGrip。1、MySQL

    2022年6月30日
    31
  • linux系统tcpdump指令抓包存为文件_tcpdump指定端口抓包

    linux系统tcpdump指令抓包存为文件_tcpdump指定端口抓包例:tcpdumphost172.16.29.40andport4600-X-s500tcpdupmhost172.16.29.40andport4600-X-s500-l-nn|teeldata.txt//可以将数据保存下来tcpdump采用命令行方式,它的命令格式为:tcpdump[-adeflnNOpqStvx][-c数量][-F…

    2022年8月20日
    4
  • iOS-class方法和objc_getClass方法

    iOS-class方法和objc_getClass方法根据上一篇博客iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别的研究发现,qi’s

    2022年6月29日
    19

发表回复

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

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