Live555 fengge's private dish (2) -- taskscheduler

Source: Internet
Author: User
Taskscheduler. These three tasks are socket handler, event handler, and delay task.
1. the socket handler is saved in the queue basictaskscheduler0: handlerset * fhandlers;
2. The event handler is saved in the array basictaskscheduler0: taskfunc * Handler [max_num_event_triggers]; 3. The delay task is saved in the queue basictaskscheduler0: delayqueue fdelayqueue. Let's take a look at the definition of the execution functions of the three types of tasks:
Socket handler is
Typedef void backgroundhandlerproc (void * clientdata, int mask );
Event Handler is
Typedef void taskfunc (void * clientdata );
Delay task is
Typedef void taskfunc (void * clientdata); // same as event handler.
Let's look at how to add three Task functions to the task scheduling object:
Socket handler:
Void setbackgroundhandling (INT socketnum, int conditionset, backgroundhandlerproc *
Handlerproc, void * clientdata)
Event Handler is:
Eventtriggerid createeventtrigger (taskfunc * eventhandlerproc)
Delay task:
Tasktoken scheduledelayedtask (int64_t microseconds, taskfunc * proc, void *
Clientdata)

Why do I need those parameters when adding socket handler? Socketnum is required because select socket
(Socketnum is the socket object returned by socket ). Conditionset is also required. It is used
Indicates which loading mode is readable when the socket is selected? Writable? Or error? Proc and clientdata
(Do you really understand ?). Let's look at the backgroundhandlerproc parameter, socketnum
What is mask? It corresponds to the conditionset, but it indicates the result after select,
For example, a socket may need to check its read/write status, but currently it can only be read but cannot be written, so there is only
Indicates that the read bit is set.
void BasicTaskScheduler  ::setBackgroundHandling(int socketNum, int conditionSet, BackgroundHandlerProc* handlerProc, void* clientData) {  if (socketNum < 0) return;  FD_CLR((unsigned)socketNum, &fReadSet);  FD_CLR((unsigned)socketNum, &fWriteSet);  FD_CLR((unsigned)socketNum, &fExceptionSet);  if (conditionSet == 0) {    fHandlers->clearHandler(socketNum);    if (socketNum+1 == fMaxNumSockets) {      --fMaxNumSockets;    }  } else {    fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData);    if (socketNum+1 > fMaxNumSockets) {      fMaxNumSockets = socketNum+1;    }    if (conditionSet&SOCKET_READABLE) FD_SET((unsigned)socketNum, &fReadSet);    if (conditionSet&SOCKET_WRITABLE) FD_SET((unsigned)socketNum, &fWriteSet);    if (conditionSet&SOCKET_EXCEPTION) FD_SET((unsigned)socketNum, &fExceptionSet);  }}

Event Handler is contained in the array. The array is fixed in size and is 32 items. eventtriggerid is used to represent
Eventtriggerid is a 32-bit integer. Because the array is 32 items
Position n 1 indicates the nth entry in the corresponding array. The member variable ftriggersawaitinghandling is also
Eventtriggerid type. The bits set to 1 in eventtriggerid correspond to all the items to be processed in the array. This saves
Memory and computing, But it reduces readability. It is not flexible enough and can only support 32 or 64 items.
Volume is not supported. The following is the function body

EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {  unsigned i = fLastUsedTriggerNum;  EventTriggerId mask = fLastUsedTriggerMask;  do {    i = (i+1)%MAX_NUM_EVENT_TRIGGERS;    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:  return 0;}

You can see that up to 32 events are added, and the clientdata parameter is not input when you add events. This parameter is
When an event is triggered, see the following functions:

void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {  // First, record the "clientData".  (Note that we allow "eventTriggerId" to be a combination of bits for multiple events.)  EventTriggerId mask = 0x80000000;  for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {    if ((eventTriggerId&mask) != 0) {      fTriggeredEventClientDatas[i] = clientData;    }    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 |= eventTriggerId;}

Check that clientdata is passed in. This indicates that clientdata can be changed every time an event is triggered. Now, go back to the page.
Is singlestep () clearer?
When a delay task is added, the number of microseconds (one second in one million) waiting for the task delay must be input (the first parameter ).
Mental Retardation can also be understood? Hey. Analyze the following functions:

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());}

The execution of the delay task is in the fdelayqueue. handlealarm () function, and handlealarm () is in the class
In delayqueue. Take a look at handlealarm ():

Void delayqueue: handlealarm () {// if the execution time of the first task is not reached, synchronize it (re-calculate the wait time of each task ). If (Head ()-> fdeltatimeremaining! = Delay_zero) synchronize (); // if the execution time of the first task reaches, execute the first task and delete it from the queue. If (Head ()-> fdeltatimeremaining = delay_zero) {// This event is due to be handled: delayqueueentry * toremove = head (); removeentry (toremove ); // do this first, in case handler accesses queue // execute the task. After the task is executed, it will be destroyed. Toremove-> handletimeout ();}}
It may be strange that other task queues search for the first item to be executed and then execute it,
Execute the first task. So it means that the first one is the one that should be executed most? That is, the one with the Shortest Waiting Time
? When adding a task, insert the new task and the data wait time to the appropriate position instead of the end.
Ba Shang? If you guess it is correct, you must check how the fdelayqueue. addentry (alarmhandler) function is executed.
Void delayqueue: addentry (delayqueueentry * newentry) {// recalculate the wait time of each item synchronize (); // obtain the first item delayqueueentry * cur = head (); // compare the wait time of the new item from start to end. While (newentry-> fdeltatimeremaining> = cur-> fdeltatimeremaining) {// If the wait time of the new item is longer than that of the current item, the wait time for the current item to be deleted. Newentry-> fdeltatimeremaining-= cur-> fdeltatimeremaining; cur = cur-> fnext;} // After the loop is completed, cur is the item that should be inserted before it, insert cur-> fdeltatimeremaining-= newentry-> fdeltatimeremaining; // Add "newentry" to the queue, just before "cur": newentry-> fnext = cur; newentry-> fprev = cur-> fprev; cur-> fprev = newentry-> fprev-> fnext = newentry ;}

There is a problem. Why didn't the while loop judge whether it reached the final code? Are you sure you can find
Is the item of the waiting time for a new item? Yes! The waiting time for the first item to be added is infinite, and this item will always exist.
In the queue.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.