📄 basetask.cpp
字号:
}
}
#endif // USE_UDP
// Create the arrays needed for global storage
// Returns 1 for successful creation; 0 for error
int BaseTask::CreateGlobal(int nGlobal)
{
PrivateGlobalData = new double [nGlobal];
GlobalData = new double [nGlobal];
if((GlobalData == NULL) || (PrivateGlobalData == NULL))return(0);
for(int i = 0; i < nGlobal; i++)
{
// Default values
PrivateGlobalData[i] = GlobalData[i] = 0.0;
}
GlobalSize = nGlobal;
return(1); // Success
}
// Copy global information from private to public view
// Returns 1 for successful; 0 for error
int BaseTask::CopyGlobal(void)
{
CriticalSectionBegin();
for(int i = 0; i < GlobalSize; i++)
{
GlobalData[i] = PrivateGlobalData[i];
}
CriticalSectionEnd();
return(1);
}
int BaseTask::AcceptGlobal(double *pData,int nData)
{
// Accept global data from an external source
if(nData != GlobalSize)
{
StopControl("<AcceptGlobal>Share array sizes don't match.\n");
exit(1);
}
CriticalSectionBegin();
for(int i = 0; i < GlobalSize; i++)
{
GlobalData[i] = pData[i];
}
CriticalSectionEnd();
return(1);
}
#ifdef USE_UDP
void StoreSharedData(int ToProc,int ToTask,int n,double *v)
{
// Interface from network functions to local task functions
BaseTask *pTask = TasksByCode[ToTask];
pTask->AcceptGlobal(v,n);
}
#endif // USE_UDP
double BaseTask::GetGlobalData(BaseTask *pb,int k)
{
CriticalSectionBegin();
double v = pb->GlobalData[k];
CriticalSectionEnd();
return(v);
}
double *BaseTask::GetGlobalArray(BaseTask *pb,int *n)
{
double *pv = pb->GlobalData; // Address of global array
*n = pb->GlobalSize;
return(pv);
}
#ifdef USE_UDP
int SendAll(void)
{
// Send out messages and shared data to other processes.
// Messages are already copied into the outgoing packets
// so nothing special has to be done with them.
// Shared data must be copied from each task for transmission
// to all other processes
// Returns success -- 1 for OK, 0 for error
BaseTask *pTask;
int ProcNo,nData;
#define BUFFER_SIZE 100
double Buffer[BUFFER_SIZE];
for(int i = 0; i < ntasks; i++)
{
// Scan all tasks
pTask = AllTasks[i];
ProcNo = pTask->GetTaskProcess();
if(ProcNo != ThisProcess)continue; // Not in this process
// therefore, don't send data
double *pData = pTask->GetGlobalArray(pTask,&nData);
if(nData <= 0)continue; // No data for this task
if(nData > BUFFER_SIZE)
{
StopControl("<SendAll> Global array too big.\n");
exit(1);
}
CriticalSectionBegin();
// Copy data to a local buffer
for(int j = 0; j < nData; j++)Buffer[j] = pData[j];
CriticalSectionEnd();
for(int j = 0; j < NumberOfProcesses; j++)
{
// Send the data to all processes except this one
if(j == ThisProcess)continue; // Don't send here
if(InsertSharedArray(j,pTask->TaskCode,nData,Buffer))
{
StopControl("<SendAll> Error inserting shared data.\n");
exit(1);
}
} // Processes
} // Tasks
if(SendData()) // Send out all available data
{
StopControl("<SendAll> Error sending data.\n");
exit(1);
}
return(1); // Normal return
}
#else // define a dummy
int SendAll(void){}
#endif // USE_UDP
// Routines for handling task lists.
// TListElement is an object to keep track of one
// BaseTask on the list. It includes a pointer to
// the next item on the list.
TListElement::TListElement(BaseTask *ItemPointer)
{
Item = ItemPointer;
Next = NULL;
}
TListElement::~TListElement(void)
{
delete (Item);
}
// TList is an object to keep track of one list of
// BaseTasks. It includes a pointer to the firts,
// last and current items on the list, as well as
// methods for finding the next item on the list,
// how many objects are on the list, and if the
// list is empty.
TList::TList(char *aName)
{
First = Last = Current = NULL;
Length = 0;
Name = new char[strlen(aName) + 1];
strcpy(Name, aName);
}
TList::~TList(void)
{
TListElement *Element = First;
TListElement *NextElement;
delete [] Name;
while (Element != NULL)
{
NextElement = Element->Next;
delete (Element);
Element = NextElement;
}
}
//-------------------------------------------------------
// Method: Append
// Add a task to the end of the list
void TList::Append(BaseTask *Item)
{
TListElement *Element = new TListElement(Item);
if(IsEmpty())
{
First = Element;
Last = Element;
Current = Element;
}
else
{
Last->Next = Element;
Last = Element;
}
Length ++;
if (Item->Name != NULL)
cout << "Added \"" << Item->Name << "\" as task: "
<< Length << " to task list \"" << Name << "\"\n";
else cout << "The task you ar trying to add as the "
<< Length << "th item on the list has no name.\n";
}
//-------------------------------------------------------
// Method: NextItem
// Return a pointer to the next time on
// the list and then set that item to the
// current item.
BaseTask * TList::NextItem(void)
{
if (IsEmpty())
return NULL;
if (Current == Last)
{
Current = First;
}
else
{
Current = Current->Next;
}
return Current->Item;
}
//-------------------------------------------------------
// Method: IsFirst
// True for empty list, false otherwise
int TList::IsEmpty(void)
{
if (First == NULL)
return 1;
else
return 0;
}
//-------------------------------------------------------
// Method: HowLong
// Returns how many items are on the list
int TList::HowLong(void)
{
return Length;
}
// TaskDispatcher
// List1 will be run as a sequential (low priority) list
// List2 will be run as a minimum latency list
// Sequential tasks each get 1 scan per call to TaskDispatcher
// Minimum latency tasks each get as many scans as they need per call
// to TaskDispatcher
// Either list or both can be empty
int TaskDispatcher (TList *List1, TList *List2)
{
BaseTask *TempTask;
int Suspend;
int List1Num,List2Num,jmax;
// Check to see which lists have entries to be run
if (List2 == NULL)
List2Num = 0;
else
List2Num = List2->HowLong();
if (List1 == NULL)
List1Num = 0;
else
List1Num = List1->HowLong();
// If both lists are empty, there is nothing to do!
if(!List1Num && !List2Num)
return (0);
// If both lists have entries, run them with List2 having
// higher priority.
if(List1Num == 0)jmax = 1; // Run outer loop once even if List1 is empty
else jmax = List1Num;
for (int j=0; j < jmax; j++)
{
for (int i=0; i < List2Num; i++)
{
if ((TempTask = List2->NextItem()) == NULL)
{// Get the next Task on the list
cout << "\nTried to access empty task list\n";
return(-1);
}
Suspend = 0;
TempTask->StartProfile();
while (Suspend != 1)
{
Suspend = TempTask->Run();
IncrementTime();
if (Suspend == -1)
{
cout << "\nProblem running Task: " <<
TempTask->Name << "\n";
TempTask->EndProfile();
return(-1);
}
}
TempTask->EndProfile();
}
if(List1Num == 0)break; // No items in List1
if ((TempTask = List1->NextItem()) == NULL)
{// Get the next Task on the list
cout << "\nTried to access empty task list\n";
return(-1);
}
TempTask->StartProfile();
Suspend = TempTask->Run(); // Run the Task
IncrementTime();
TempTask->EndProfile();
if (Suspend == -1)
{
cout << "\nProblem running Task: " <<
TempTask->Name << "\n";
return(-1);
}
}
return (0);
}
// System dependent call to disable all maskable interrupts.
void DisableInterrupt (void)
{
#ifdef ISR_SCHEDULING
_disable();
#endif // ISR_SCHEDULING
}
// System dependent call to enable all maskable interrupts.
void EnableInterrupt (void)
{
#ifdef ISR_SCHEDULING
_enable();
#endif // ISR_SCHEDULING
}
// Sections of code which needs to be protected against
// preemption should be bracketed by calls to CriticalSectionBegin()
// and CriticalSectionEnd(). This method is preferred to diabling
// interrupts because the interrupt helps to keep track of time
// when the combination of interrupts and Timer0 are used.
// If the CriticalSection flag is set to 1, the scheduling in the
// interrupt is diabled
static int CriticalSection = 0;
static int CriticalCounter = 0; // Used to indicate when to actually end a
// critical section -- this is done so nested critical sections are handled
// properly.
// void CriticalSectionBegin (void)
// Do not allow interrupt scheduling to occur after a call to
// this function until CriticalSectionEnd() is subsequently called.
void CriticalSectionBegin (void)
{
DisableInterrupt();
CriticalCounter++; // Increment for each entry
CriticalSection = 1;
EnableInterrupt();
}
// void CriticalSectionEnd (void)
// Allow the interrupt to resume scheduling tasks.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -