[live555] 谈一谈 HandlerIterator \ HandlerDescriptor \HandlerSet 构成迭代器

前因

在 创建 live555 服务的时候

  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);

会创建

BasicTaskScheduler0::BasicTaskScheduler0()
: fLastHandledSocketNum(-1)
, fTriggersAwaitingHandling(0)
,fLastUsedTriggerMask(1)
,fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1)
 {
  fHandlers = new HandlerSet;  //初始化 HandlerSet 实例fHandlers
//....
}

但是在创建rtspserver 的时候 执行 assignHandler

fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData);

进一步查看源码
发现被 HandlerSet HandlerDescriptor HandlerIterator 的关系绕晕了,所以特地拉出来分析

因为 HandlerSet 实例 fHandlers ,但是 HandlerSet 类中私有HandlerDescriptor 实例也是fHandlers,所以看代码的时候要特别注意
首先查看HandlerSet对象 声明 ,用来事件处理

class HandlerSet {
public:
  HandlerSet();
  virtual ~HandlerSet();
  void assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData);
  void clearHandler(int socketNum);
  void moveHandler(int oldSocketNum, int newSocketNum);
private:
  HandlerDescriptor* lookupHandler(int socketNum);
private:
  friend class HandlerIterator;
  HandlerDescriptor fHandlers;//就是这个对象,在看源码的时候要注意
};

HandlerDescriptor 相当与一个基本单元对象 存放有前节点地址 后节点地址

class HandlerDescriptor {
  HandlerDescriptor(HandlerDescriptor* nextHandler);
  virtual ~HandlerDescriptor();
public:
  int socketNum;
  int conditionSet;
  TaskScheduler::BackgroundHandlerProc* handlerProc;
  void* clientData;
private:
  // Descriptors are linked together in a doubly-linked list:
  friend class HandlerSet;
  friend class HandlerIterator;
  HandlerDescriptor* fNextHandler;
  HandlerDescriptor* fPrevHandler;
};

HandlerIterator 类 迭代器,遍历 HandlerDescriptor

class HandlerIterator {
public:
  HandlerIterator(HandlerSet& handlerSet);
  virtual ~HandlerIterator();
  HandlerDescriptor* next(); // returns NULL if none
  void reset();
private:
  HandlerSet& fOurSet;
  HandlerDescriptor* fNextPtr;
};

分析逻辑源码

逻辑代码 在进行 assignHandler时


void HandlerSet::assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData) {
  // First, see if there's already a handler for this socket:
  HandlerDescriptor* handler = lookupHandler(socketNum);
  if (handler == NULL) { // No existing handler, so create a new descr:
    handler = new HandlerDescriptor(fHandlers.fNextHandler);
    handler->socketNum = socketNum;
  }

  handler->conditionSet = conditionSet;
  handler->handlerProc = handlerProc;
  handler->clientData = clientData;
}
  1. 在HandlerDescriptor 和socketNum 对应关系表 查看socketNum 对应的HandlerDescriptor
  2. 如果没有找到,即handler == NULL 重新创建HandlerDescriptor 和 socketNum 的关系
  3. 初始化HandlerDescriptor 的三个变量conditionSet (条件集合) handlerProc(处理方法) clientData(被处理的对象)

很明显需要查看 lookupHandler 函数 .这个函数有点绕


HandlerDescriptor* HandlerSet::lookupHandler(int socketNum) {
  HandlerDescriptor* handler;
  HandlerIterator iter(*this);
  while ((handler = iter.next()) != NULL) {
    if (handler->socketNum == socketNum) break;
  }
  return handler;
}

上面的代码通过HandlerIterator 遍历获取HandlerDescriptor的实例 handler ,但是HandlerIterator迭代器用HandlerSet来初始化 这里的this是 正在运行HandlerSet 实例fHandlers

根据上面 类的声明, HandlerSet& fOurSet; 是 HandlerIterator 私有变量,带参数的构造
查看 HandlerIterator 构造函数实现

HandlerIterator::HandlerIterator(HandlerSet& handlerSet)
  : fOurSet(handlerSet) {
  reset();
}

void HandlerIterator::reset() {
  fNextPtr = fOurSet.fHandlers.fNextHandler;
}

初始化 fOurSet 后 ,就开始遍历查看 next()实现

HandlerDescriptor* HandlerIterator::next() {
  HandlerDescriptor* result = fNextPtr;
  if (result == &fOurSet.fHandlers) { // no more
    result = NULL;
  } else {
    fNextPtr = fNextPtr->fNextHandler;
  }
  return result;
}

这里 有 fNextPtr 和 fNextPtr = fNextPtr->fNextHandler; 就说明 HandlerIterator next()是进行链表的下一个元素访问
如果fNextPtr 存在 ,fNextPtr就变成访问 下一个元素 HandlerDescriptor ,但是 当前HandlerDescriptor 被赋值在result 和 &fOurSet.fHandlers 相同就为null,这样就说明 这个socketnum 和HandlerDescriptor 对应关系存在,不用增加
这里的 fOurSet就是HandlerSet fHandlers ,fHandlers .fHandlers 就是访问 成员变量HandlerDescriptor fHandlers

但是这里是第一次创建 所以返回null ,因此最后会创建一个HandlerDescriptor 和 socketnum 关系


  if (handler == NULL) { // No existing handler, so create a new descr:
    handler = new HandlerDescriptor(fHandlers.fNextHandler);
    handler->socketNum = socketNum;
  }
HandlerDescriptor::HandlerDescriptor(HandlerDescriptor* nextHandler)
  : conditionSet(0), handlerProc(NULL) {
  // Link this descriptor into a doubly-linked list:
  if (nextHandler == this) { // initialization
    fNextHandler = fPrevHandler = this;
  } else {
    fNextHandler = nextHandler;
    fPrevHandler = nextHandler->fPrevHandler;
    nextHandler->fPrevHandler = this;
    fPrevHandler->fNextHandler = this;
  }
}

这个实现思想,也是很绕的,基本上就是这个看代码思路

总结下, HandlerIterator 操作的其实是HandlerDescriptor 的上一个节点地址和下一个节点地址,而HandlerSet用来保存实例 HandlerDescriptor,最后将自己送给 HandlerIterator,被HandlerIterator 迭代器操作,准确来说操作的是保存在HandlerSet 中的HandlerDescriptor 实例

反正代码逻辑怪怪的,决定只需要记住功能就好了,主要是跟踪 socket 才分析的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值