这个c++库可以自动管理unique_ptr

源:https://github.com/zgww/urgc
恳请各位大佬点个star

urgc

unique reference garbage collect

简介

一个c++库。用法类似于智能指针,同时解决循环引用的问题,也不需要开发者特意标注强弱引用.

初心

c++性能极高,能充分利用机器的性能。随着c++的升级, 加入了很多优秀特性,如lambda, 协程, module,
极大地提高了开发效率。 但是内存管理还是很棘手。

虽然有智能指针,但是在游戏开发,GUI领域,对象引用关系复杂,循环引用 不可避免,所有权也不清晰,使用智能指针还是得
非常小心,才能避免泄漏。

作者希望此库为开发者带来更好的开发体验,为用户带来又快又轻巧又炫的软件。

与可达性分析型gc的区别

可达性分析型gc,遍历活着的对象,然后把没有遍历到的对象释放掉。
urgc可以认为遍历可能死亡的对象,释放真的死亡的对象,重新整理未真实死亡的对象的引用

因为是遍历可能死亡的对象,所以urgc具有局部性,不像可达性分析gc需要遍历完整对象图

与引用计数的区别

引用计数为了避免循环引用,需要特意标注弱引用.

urgc可以处理循环引用,也有相应的环遍历的代价

环遍历

遍历循环引用,是不可避免的。

举个极端的例子,有1百万个对象引用成环,

除了遍历引用链,第0个对象,是没有办法知道, 离它50万个引用外的对象b跟它是不是构成了循环引用。

有可能对象b引用了对象c,就导致了一个有1百万个对象的环成立,

对象b解引用对象c,就导致了一个有1百万个对象的环解体。

用法

最简单的例子

#include "Urgc.h"

class User {
public:
    int age;
};

int main(){
    Local user = new User();
    ///出了作用域后,user就会自动释放掉
    return 0;
}

lambda

内存管理,管理的是堆上的内存,所以lambda也需要封装到堆上。

#include "Urgc.h"

class User {
public:
    int age;
};
auto get_cb(){
    Local user = new User();
    user->age = 923;
    //
    auto fn = CLOSURE([=](){
        printf("hi urgc: user age:%d\n", user->age);
    });
    return fn;
}
int main(){
    auto fn = get_cb();
    fn->call(); //此处打印出: hi urgc: user age: 923
    ///出了作用域, fn和user都会被释放掉
    return 0;
}

循环引用

#include "Urgc.h"

class Node {
public:
    //此处的this,是为了让Local知道谁是引用的主体
    Local other{nullptr, this};
    Local other2{nullptr, this};
};
void say(){
    Local a = new Node();
    Local b = new Node();
    Local c = new Node();
    Local d = new Node();
    //循环引用
    a->other = b;
    b->other = a;
    
    a->other2 = c;
    c->other = d;
    d->other = a;
    d->other2 = b;
    //出了作用域后,a和b,c,d都会释放掉
}
int main(){
    say();
    return 0;
}

ConsoleApplication1.cpp有以上的测试代码

原理

引用计数,如果要解决循环引用,可以在release引用时,遍历引用,判断是否成环。

但是实践中,是做不到的,因为遍历引用的代价太大了。

urgc是在引用计数上加以改进。

urgc引入一条规则: 一个对象可以被多个对象强引用,但是同一时间,只有一个强引用被标记为主引用

这条规则的作用是:在对象引用图上,构建了主引用树。树的定义,是可以保证不会有环出现。

主引用树的作用是:当且仅当主引用被释放时,遍历主引用树,为树下的对象寻找新的主引用,如果有找到,就说明对象

有别的主引用树接纳,可以存活,没有就说明是死亡对象,可以释放。

主引用树,就是自动管理的唯一所有权

性能

在GUI环境下测试,几百个节点,性能消耗约为 delete 函数的4倍

独立的gc线程

目前实现,是借助RAII,在当前线程下加减引用。

优点是可以做到立即释放,缺点是有性能代价,而且没办法充分利用多线程。

希望能将加减引用转为事件,交给独立的gc线程处理。 这样对工作线程的压力就极小。

适用场景

想像一下,一个GUI应用,c++写的,本身性能就极高,而且也不会因为触发gc,导致掉帧,那体验该有多丝滑。

路线

[x] 省略lambda类型声明

[x] 线程安全

[ ] 独立的gc线程

[ ] 补充更多的测试

[ ] 性能测试

[ ] 用于实战: 基于urgcskia 构建 GUI

[ ] 用于实战: GUI editor

你可能感兴趣的:(这个c++库可以自动管理unique_ptr)