分布式软总线中的调度器模式
一.是什么
调度器模式算是设计模式中的一种
调度器模式 = 在统一接口之下,根据能力位图(capabilityBitmap)将请求路由到不同的具体实现。
本质上是 策略模式 + 路由表 的结合:
- 策略模式:所有子实现提供相同的
DiscoveryFuncInterface接口 - 路由表:每个子实现注册一个
IsConcern谓词,调度器遍历路由表找到匹配的实现
二、为什么需要
BLE 发现不是一种,而是6 种业务场景共用 BLE 介质:
| 子实现 | 关注的能力 | 业务场景 |
|---|---|---|
| SoftBus BLE | castPlus, dvKit, osd | 通用分布式发现 |
| Share BLE | share | 跨设备分享 |
| Approach BLE | approach | 靠近发现 |
| VLink BLE | virtualLink | 虚拟链路 |
| Touch BLE | touch | 触碰发现 |
| OOP BLE | oop | OOP 发现 |
问题:Manager 层只给 BLE 一个 DiscoveryFuncInterface 指针,BLE 内部怎么区分这 6 种场景?
答案:加一层 Dispatcher,根据请求的 capabilityBitmap 自动路由到对应的子实现。
三、核心数据结构
DispatcherInterface — 路由表条目
从 disc_ble_dispatcher.h:35:
typedef struct {
bool (*IsConcern)(uint32_t capability); // 路由谓词:"我是否关注这个能力?"
DiscoveryFuncInterface *mediumInterface; // 具体实现接口
} DiscoveryBleDispatcherInterface;
路由表 — Dispatcher 数组
#define DISPATCHER_SIZE 6
static DiscoveryBleDispatcherInterface *g_dispatchers[DISPATCHER_SIZE]; // 6个槽位
static uint32_t g_dispatcherSize = 0; // 当前注册数
每个子实现的 IsConcern
| 子实现 | IsConcern 实现 | 关注的能力掩码 |
|---|---|---|
| SoftBus BLE | (capability & g_concernCapabilityMask) != 0 |
1<<3 | 1<<5 | 1<<7 (castPlus, dvKit, osd) |
| Share BLE | IsShareConcern(capability) |
1<<8 (share) |
| Approach BLE | IsApproachConcern(capability) |
1<<9 (approach) |
| VLink BLE | return false (virtual实现) |
1<<10 (virtualLink) |
| Touch BLE | return false (virtual实现) |
1<<11 (touch) |
| OOP BLE | return false (virtual实现) |
1<<12 (oop) |
注意:VLink/Touch/OOP 的 virtual 实现
IsConcern返回 false,表示当前平台不支持,真实实现(非 virtual)会返回对应的判断。
四、调度流程
请求到达时的路由过程

FindDiscoveryFuncInterface 核心代码
static DiscoveryFuncInterface *FindDiscoveryFuncInterface(uint32_t capability)
{
for (uint32_t i = 0; i < g_dispatcherSize; i++) {
if (g_dispatchers[i] == NULL) continue;
if (g_dispatchers[i]->IsConcern != NULL &&
g_dispatchers[i]->IsConcern(capability)) { // ★ 路由判断
return g_dispatchers[i]->mediumInterface; // ★ 返回匹配的实现
}
}
return NULL; // 无匹配,返回NULL,调用方报错
}
五、初始化:注册路由表
从 disc_ble_dispatcher.c:226:
DiscoveryFuncInterface *DiscBleInit(DiscInnerCallback *discInnerCb)
{
g_dispatcherSize = 0;
// 注册5个基础 Dispatcher
g_dispatchers[0] = DiscSoftBusBleInit(discInnerCb); // SoftBus BLE (通用)
g_dispatchers[1] = DiscShareBleInit(discInnerCb); // Share BLE (分享)
g_dispatchers[2] = DiscApproachBleInit(discInnerCb); // Approach BLE (靠近)
g_dispatchers[3] = DiscVLinkBleInit(discInnerCb); // VLink BLE (虚拟链路)
// 注册扩展 Dispatcher
DiscBleInitExt(discInnerCb);
// g_dispatchers[4] = DiscTouchBleInit(discInnerCb); // Touch BLE (触碰)
// g_dispatchers[5] = DiscOopBleInit(discInnerCb); // OOP BLE
return &g_discBleFrameFuncInterface; // 返回统一接口给 Manager
}
每个 DiscXxxBleInit 返回一个 DiscoveryBleDispatcherInterface,包含该子实现的 IsConcern 和 mediumInterface。
六、统一接口:Dispatcher 对 Manager 透明
Dispatcher 向上暴露一个 DiscoveryFuncInterface,Manager 完全不知道 Dispatcher 的存在:
static DiscoveryFuncInterface g_discBleFrameFuncInterface = {
.Publish = BleDispatchStartActivePublish,
.StartScan = BleDispatchStartPassivePublish,
.Unpublish = BleDispatchStopActivePublish,
.StopScan = BleDispatchStopPassivePublish,
.StartAdvertise = BleDispatchStartActiveDiscovery,
.Subscribe = BleDispatchStartPassiveDiscovery,
.StopAdvertise = BleDispatchStopActiveDiscovery,
.Unsubscribe = BleDispatchStopPassiveDiscovery,
.LinkStatusChanged = BleDispatchLinkStatusChanged,
.UpdateLocalDeviceInfo = BleDispatchUpdateLocalDeviceInfo,
};
每个函数内部都走 FindDiscoveryFuncInterface → 具体实现的路由流程。
七、完整结构关系图

八、USB Dispatcher — 完全对称的设计
USB 发现采用完全相同的调度器模式,只是当前只有 1 个 Dispatcher:
#define DISPATCHER_SIZE 1
static DiscoveryUsbDispatcherInterface *g_usbDispatchers[DISPATCHER_SIZE];
路由逻辑与 BLE Dispatcher 代码几乎一模一样,只是把 g_dispatchers 换成 g_usbDispatchers。
九、调度器模式 vs 其他方案
| 方案 | 优点 | 缺点 |
|---|---|---|
| 调度器模式(当前) | 新增子实现只需注册 Dispatcher,不改调度逻辑 | 每次请求遍历路由表 O(N) |
| if-else 硬编码 | 简单直接 | 新增能力必须改调度代码,违反开闭原则 |
| 位图直接映射数组 | O(1) 查找 | 一个能力只能对应一个实现,无法表达"SoftBus BLE 关注多种能力" |
| 虚函数/接口继承 | 面向对象自然分发 | C 语言没有虚函数,需手动实现 vtable |
当前方案的核心优势:IsConcern 是谓词而非等值匹配,所以 SoftBus BLE 可以一次声明关注 castPlus + dvKit + osd 三种能力,而不需要注册 3 次。这是位图直接映射做不到的。
更多推荐
所有评论(0)