鸿蒙源码分析(六十二)

iunknown.c文件

文件主要目的为系统功能的外部功能提供基类和默认实现
文件路径:ddistributedschedule_samgr_lite\samgr\source\iunknown.c

代码部分

1.IUNKNOWN_AddRef

函数功能:添加一个引用计数

#define OLD_VERSION 0
//添加一个引用计数
int IUNKNOWN_AddRef(IUnknown *iUnknown)
{
    
    
    if (iUnknown == NULL) {
    
    
        return EC_INVALID;
    }

    IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown);
    //将指针转换为IUnknownEntry类型
    entry->ref++;//计数变量增加
    return entry->ref;
}

2.IUNKNOWN_QueryInterface

函数功能:查询指定版本IUnknown接口的子类对象

//接口的查询
//查询指定版本IUnknown接口的子类对象
int IUNKNOWN_QueryInterface(IUnknown *iUnknown, int ver, void **target)
{
    
    
    if (iUnknown == NULL || target == NULL) {
    
    
        return EC_INVALID;
    }

    IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown);
    if ((entry->ver & (uint16)ver) != ver) {
    
    
        return EC_INVALID;
    }

    if (ver == OLD_VERSION &&
        entry->ver != OLD_VERSION &&
        (entry->ver & (uint16)DEFAULT_VERSION) != DEFAULT_VERSION) {
    
    
        return EC_INVALID;
    }
    //检查版本
    *target = iUnknown;
    iUnknown->AddRef(iUnknown);
    return EC_SUCCESS;
}

3.IUNKNOWN_Release

函数功能:释放一个接口

//接口的释放
int IUNKNOWN_Release(IUnknown *iUnknown)
{
    
    
    if (iUnknown == NULL) {
    
    
        return EC_INVALID;
    }

    IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown);
    int ref = entry->ref - 1;
    if (ref < 0) {
    
    
        // The iUnknown is already freed, there is some exception;
    } else {
    
    
        if (ref == 0) {
    
    
            // Nobody reference to the iUnknown, should delete it.
            // But iUnknown may be global variable, so the default version don`t delete it.
        } else {
    
    
            entry->ref = ref;
        }
    }
    return ref;
}

个人思路理解

首先是addref函数,这个函数是添加一个接口引用计数,引用的计数主要是query时候才会实现,所以正常的声明定义并不会引用接口,之后查询接口时候才会出现引用情况,所以这个函数的使用都在QueryInterface函数中,而且这个函数机制的实现并没有锁的保护,所以多个QueryInterface函数执行并发控制有一定难度。所以多端开发需要重新实现

其次是queryinterface函数,这个函数就是查询指定版本的iunknown接口,查询之后将类型转换为我们需要的版本子类型,如果不能满足要求就会重新执行该函数

最后,释放函数并不是释放接口,而是释放一个对接口的引用,如果一个接口的引用属性ref为0,说明未被引用,所以这个对应的接口不会被释放。这个是系统默认函数的实现,但是在该函数中,ref为0时也会被释放内存中的空间

感谢阅读和支持,欢迎指正!

猜你喜欢

转载自blog.csdn.net/m0_46976252/article/details/120633175