swoole源码分析之Buffer的write操作

swoole_buffer提供的write操作用于向缓存区的任意内存位置写数据。read/write函数可以直接读写内存。所以使用务必要谨慎,否则可能会破坏现有数据。

swoole_buffer->write(int $offset, string $data)
  • $offset 偏移量
  • $data 写入的数据

现在我们看下其处理流程。

static PHP_METHOD(swoole_buffer, write)
{
    long offset;
    swString str;

    bzero(&str, sizeof(str));//内存空间初始化

    //解析输入参数信息,这里输入参数有offset和要写入的数据data,其中offset表示要从哪里开始写入
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &offset, &str.str, &str.length) == FAILURE)
    {
        RETURN_FALSE;
    }

    if (str.length < 1)//要写入数据异常
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "string to write is empty.");
        RETURN_FALSE;
    }

    swString *buffer = swoole_get_object(getThis());//获取swoole内部封装对象

    if (offset < 0)//从buffer的尾部开始写入
    {
        offset = buffer->length - buffer->offset + offset;//转换输入offset,调整后变为从头开始计算
    }

    if (offset < 0)//offset越界
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset(%ld) is out of bounds.", offset);
        RETURN_FALSE;
    }

    offset += buffer->offset;//计算offset信息,业务输入的offset是以buffer目前的offset为基准计算的 

    if ((str.length + offset) > buffer->size && (str.length + offset) > SW_STRING_BUFFER_MAXLEN)//判断要写入的数据是否超出buffer容量和最大容量
    {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "buffer size can't exceed %d", SW_STRING_BUFFER_MAXLEN);
        RETURN_FALSE;
    }

    size_t size_old = buffer->size;
    if (swString_write(buffer, offset, &str) == SW_OK)
    {
        if (buffer->size > size_old)//buffer有扩容
        {
            zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("capacity"), buffer->size TSRMLS_CC);//更新swoole_buffer对象的属性capacity信息
        }
        zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("length"),
                buffer->length - buffer->offset TSRMLS_CC);//更新swoole_buffer对象的属性length信息
        RETURN_LONG(buffer->length - buffer->offset);
    }
    else
    {
        RETURN_FALSE;
    }
}
int swString_write(swString *str, off_t offset, swString *write_str)
{
    int new_length = offset + write_str->length;//要写入数据占用空间大小
    if (new_length > str->size)//大于目前buffer的容量
    {
        //执行扩容,按new_legth的2倍扩容,进行内存对齐,对齐的大小为系统page大小
        if (swString_extend(str, swoole_size_align(new_length * 2, sysconf(_SC_PAGESIZE))) < 0)
        {
            return SW_ERR;
        }
    }

    memcpy(str->str + offset, write_str->str, write_str->length);//数据拷贝

    if (new_length > str->length)//写入数据有增长,更新buffer的length属性
    {
        str->length = new_length;
    }

    return SW_OK;
}
static sw_inline size_t swoole_size_align(size_t size, int pagesize)
{
    return size + (pagesize - (size % pagesize));//内存对齐
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值