zoukankan      html  css  js  c++  java
  • 20 BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。

    本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso/
    本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso

    scheduleDelayedTask方法(调度延时任务)

    scheduleDelayedTask方法有三个参数,分别是时间microseconds,任务proc,数据clientData
    其使用这三个参数创建一个定时处理程序对象AlarmHandler(proc, clientData, timeToDelay),并将这个对象添加到延时队列链表中管理起来。返回了一个这个对象的唯一标识token。

    TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds,
    						 TaskFunc* proc,
    						 void* clientData) {
      if (microseconds < 0) microseconds = 0;
      DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000));
      AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay);
      fDelayQueue.addEntry(alarmHandler);
    
      return (void*)(alarmHandler->token());
    }
    unscheduleDelayedTask方法(取消调度延时任务)
    unscheduleDelayedTask方法将pervTask代表的节点从延时队列中移除,并销毁。参数类型TaskToKen实质是一个void*型。其应该传入的是一个AlarmHandler对象的token标识。
    void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken& prevTask) {
      DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask);
      prevTask = NULL;
      delete alarmHandler;
    }
    

    doEventLoop方法(事件处理循环)

    这是一个死循环,在符合条件的时候,会不断调用SingleStep。这个方法是做一次事件轮询处理。参数watchVariable是用来控制是否继续循环的,如果它指向的地址的内容不是’’,那么就会跳出死循环,不再继续。
    SingleStep在派生类BasicTaskScheduler中实现。

    void BasicTaskScheduler0::doEventLoop(char* watchVariable) {
    	// Repeatedly loop, handling readble sockets and timed events:
    	// 反复循环,可读取套接字和定时事件的处理:
    	while (1) {
    		if (watchVariable != NULL && *watchVariable != 0) break;
    		SingleStep();
    	}
    }
    

    createEventTrigger方法(创建事件触发器)

    这个方法将参数eventHandlerProc在数组fTriggeredEventHandlers还有空位的时候将其添加到数组中,然后返回一个指示其被添加到数组fTriggeredEventHandlers中的位置的的变量。

    EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {
    	unsigned i = fLastUsedTriggerNum;	//最后使用的触发器在数组的下标
    	EventTriggerId mask = fLastUsedTriggerMask;	//bit位置
    
    	do {
    		i = (i + 1) % MAX_NUM_EVENT_TRIGGERS;	//0-31之间
    		mask >>= 1;		//向左移位,与下标同步
    		if (mask == 0) mask = 0x80000000;
    		//找到一个未使用的位置,就将事件处理程序地址保存到此处
    		if (fTriggeredEventHandlers[i] == NULL) {
    			// This trigger number is free; use it:
    			fTriggeredEventHandlers[i] = eventHandlerProc;
    			fTriggeredEventClientDatas[i] = NULL; // sanity
    			//更新这两个至
    			fLastUsedTriggerMask = mask;
    			fLastUsedTriggerNum = i;
    			//这个返回值可以求得上面的数组位置值
    			return mask;
    		}
    	} while (i != fLastUsedTriggerNum);
    
    	// All available event triggers are allocated; return 0 instead:
    	// 所有可用的事件触发都被分配;而返回0:
    	return 0;
    }
    

    deleteEventTrigger方法(删除事件触发器)

    deleteEventTrigger方法将eventTriggerId标识的(非0位置)触发器从数组fTriggeredEventHandlers中移除。
    fTriggersAwaitingHandlingtriggeredEvent方法中修改了。

    void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {
    	//fTriggersAwaitingHandling是等待触发处理位标识(标识数组fTriggeredEventHandlers已使用)
    	//那么这儿很好理解,就是eventTriggerId中不为0的位,在对应的fTriggersAwaitingHandling中清零
    	//相当于是标识fTriggeredEventHandlers相应的位置已经被释放了。
    	fTriggersAwaitingHandling &= ~eventTriggerId;
    
    	if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
    		fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL;
    		fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL;
    	}
    	else {
    		// "eventTriggerId" should have just one bit set.其可能是一个集合(要删除多个触发器)
    		// However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s:
    		//从将数组对应的位置清零
    		EventTriggerId mask = 0x80000000;
    		for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
    			if ((eventTriggerId&mask) != 0) {
    				fTriggeredEventHandlers[i] = NULL;
    				fTriggeredEventClientDatas[i] = NULL;
    			}
    			mask >>= 1;
    		}
    	}
    }
    
    

    triggerEvent方法(触发事件)

    triggerEvent并没有真正的触发事件,而是将参数eventTriggerId标识的位置,在fTriggeredEventClientDatas数组中对应的元素的值改为clientData
    之前创建触发器的时候,将fTriggeredEventClientDatas数组的对应位置是置为NULL的。

    void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {
    	// First, record the "clientData":首先,记录“客户端数据”:
    	if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
    		fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
    	}
    	else {
    		EventTriggerId mask = 0x80000000;
    		for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
    			if ((eventTriggerId&mask) != 0) {
    				fTriggeredEventClientDatas[i] = clientData;
    
    				fLastUsedTriggerMask = mask;
    				fLastUsedTriggerNum = i;
    			}
    			mask >>= 1;
    		}
    	}
    
    	// Then, note this event as being ready to be handled.
    	// (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to
    	//  reduce the risk of a race condition.)
    	//  将fTriggersAwaitingHandling中对应的位置1。
    	fTriggersAwaitingHandling |= eventTriggerId;
    }
    
  • 相关阅读:
    梯度下降
    最小二乘法模型的推导原理
    斗图啦+多线程(队列)
    scrapy错误-[scrapy.core.scraper] ERROR: Spider error processing
    python使用requests时报错requests.exceptions.SSLError: HTTPSConnectionPool
    AttributeError: module 'requests' has no attribute 'get'的错误疑惑
    *arg,**kwargs的参数作用的疑惑
    scrapy框架--新建调试的main.py文件
    Scrapy框架——安装以及新建scrapy文件
    爬虫-ajax请求遇到Unicode编码问题
  • 原文地址:https://www.cnblogs.com/oloroso/p/4599973.html
Copyright © 2011-2022 走看看