dreamlike-ocean / PanamaUring

使用panama api为java提供io_uring的绑定而无需使用jni绑定,同时统一文件IO和网络IO的模型,提供一套易用的异步IO API
MIT License
77 stars 12 forks source link

使用SmallRye Mutiny改造全部的异步接口 and jdk21适配 and 应用瘦身 #23

Closed dreamlike-ocean closed 11 months ago

dreamlike-ocean commented 1 year ago

当前项目中存在one shot和multi shot两种模式的异步效应 前者的异步接口为completefuture和conumer,非常不统一且存在大量的接口形成时间远早于cancel接口,因此api方面风格不够统一 对于multi shot模式则是使用自定义的reactive flow实现,虽然是jdk接口但是实现的不够通用且不够健壮 综上,我更倾向于使用成熟的异步库来帮助实现更统一的接口风格 参考 https://smallrye.io/smallrye-mutiny/2.3.1/

He-Pin commented 1 year ago

没有用过,这个库和reactor-core对比呢

dreamlike-ocean commented 1 year ago

没有用过,这个库和reactor-core对比呢

reactor,rxjava,mutiny本质上都差不多,选一个用就好了 这边我选mutiny只是个人爱好

dreamlike-ocean commented 1 year ago

感觉实现不了。。。 这样这样的一个接口(这里的实现是错的)

    protected Uni<Integer> writeUnsafeLazy(int offset, MemorySegment memorySegment) {
        if (closed.get()) {
            throw new NativeCallException("file has closed");
        }
        Uni<Integer> lazyRes = Uni.createFrom()
                .emitter((ue) -> {
                    AtomicLong userDataLazy = new AtomicLong();
                    long userData = ioUring.prep_write_and_get_user_data(writeFd(), offset, memorySegment,
                            (writeRes) -> {
                                ue.complete(writeRes);
                            });
                    if (userData == IOUring.NO_SQE) {
                        ue.fail(new NotEnoughSqeException());
                        return;
                    }
                    ue.context().put(USER_DATA_KEY, userData);
                    userDataLazy.set(userData);
                });

        return lazyRes.withContext((uni, c) -> {
            Long userData = c.get(USER_DATA_KEY);
// uni.onCancellation() .call(() -> eventLoop.cancelAsync(userData, 0, true));
// 这个call的语义是The upstream is not cancelled yet, but will be cancelled when the returned {@link Uni} completes
// 所以无论是否取消成功他都会设置流为取消状态
//思考这样一个场景,MemorySement为一池化内存,下游在cancel的回调里面设置当cancel时归还内存
//此时发起取消,但是此时已经进去写fd的环节导致取消失败,但是由于直接设置流为cancel 内存可以被复用了,
//此时有个其余的线程拿到了这个MemorySegement并进行写入操作,此时os仍在写入fd,写入的东西就是不可预知的了
            return uni.onCancellation()
                    .call(() -> eventLoop.cancelAsync(userData, 0, true));
        });
    }
dreamlike-ocean commented 1 year ago

【【达坦科技】4.8 Beijing Rust Meetup|茌海《Monoio:一个基于 io-uring 的 Rust Runtime》-哔哩哔哩】 https://b23.tv/JVkyPFO 我可能从一开始就是错的。。。异步所有权的问题 看起来得做点更复杂的取消逻辑 or 干脆摆烂不做取消 甚至重新设计。。。

dreamlike-ocean commented 1 year ago

目前采用构建所有权的方式实现 给出一个


public interface OwnershipMemory {
    MemorySegment resource();

    void drop();
}

这样的接口给用户,以示转移所有权给io_uring侧,若用户和io_uring侧同时都在修改这个资源甚至用户把他释放了,这种情况属于UB。。。。没有办法通过编译器来约束,只能做个约定

dreamlike-ocean commented 1 year ago

目前改造使用所有权的约定,只有当异步操作正常完成且没有被cancel的场景才将OwnershipMemory发送到下游,其余情况直接在io_uring eventloop侧释放这个所有权