⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basetask.cpp

📁 a program that generates a pulse-width modulated (PWM)signal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Base class for task template.
// File:  basetask.cpp
// Created 8/2/95 by Jason Jones
// Modifications:
//      8/23/95 - JJ added TList.Name and cout in
//                                       TList.Append.
//     10/6/95, DM Auslander, added task ID numbers
//      9/11/96, DM Auslander, added task profiling
//     10/1/96, DM Auslander, added message passing
//     10/7/96, DM Auslander, added global data base
//      6/16/97, DM Auslander, added state names for audit trail

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <dos.h>
#include <stdarg.h>
#include "tasks.hpp"


#define NTASKSMAX 50    // For use in ScanStat section
// These arrays are filled in InitScanStat()
static int ntasks=0;
// These arrays use TaskID as the index
static char *tskname[NTASKSMAX];        // This isn't really needed
                                // but it's convenient!
BaseTask *AllTasks[NTASKSMAX];

// This array uses TaskCode as its index
BaseTask *TasksByCode[2 * NTASKSMAX];  // Extra space because TaskCode
        // can be assigned arbitrarily

static task_id = -1;    // Use this to get a running index of tasks

#ifndef PROCESS_INFO  // Default process information for code that
   // does not have process information in tasks.hpp
const int ThisProcess = 0; // Process number
const int NumberOfProcesses = 1;  // Number of independent processes
#endif

void BaseTask::BaseTaskInit(char *aName,int ProcNo)
    {
    Name = new char[strlen(aName)+1];
    strcpy(Name, aName);
    task_id++;      // Index the id #
    TaskID = task_id;
    TaskCode = TaskID;  // Always the same as TaskID
    NumScans = 0;
    State = xState = 0;
    NextState = 0;
    RunEntry = 0;
    InitScanStat(this);
    ProcessNo = ProcNo;
    if(TaskCode >= (NTASKSMAX))
        {
      cout << "<BaseTaskInit> Task code too big (>2*NTASKSMAX)\n";
      exit(1);
      }
    TasksByCode[TaskCode] = this;  // Pointer to this task
    GlobalSize = 0;  // Default is no global data
    StateNames = NULL;  // No state names defined yet
    };

BaseTask::BaseTask(char *aName,int ProcNo)  // Constructor
    {
    profile_on = 0;  // Default is no profiling
    BaseTaskInit(aName,ProcNo);
    }

// The destructor is overloaded in the derived task
BaseTask::~BaseTask(void)
   {
   delete [] Name;
   if(profile_on)
       {
       // Free space used by profiler
       delete [] values;
       delete [] occur;
       }
   if(GlobalSize > 0)
      {
      // Free space used for globals
      delete [] PrivateGlobalData;
      delete [] GlobalData;
      }
   if(StateNames != NULL)delete [] StateNames;
   }

static char *DefName = "aState";

// Functions to name states
void BaseTask::CreateStateNameArray(int n)
    {
    StateNames = new char * [n];
    nStateNames = n;
    for(int i = 0; i < n; i++)StateNames[i] = DefName;
    }

void BaseTask::RegisterStateName(char *pName,int i)
    {
    if(i >= nStateNames)
        {
        cout << "RegisterStateName> Index too large\n";
        exit(1);
        }
    StateNames[i] = pName;
    }

char **BaseTask::GetStateNames(void)
    {
    return(StateNames);
    }

// The default Run() function should never actually
// be used.  It should be overloaded in the actual
// task definition.
int BaseTask::Run(void)
        {
        StopControl("Run function not overloaded\n");
        return (1);
        }

long BaseTask::GetNumScan(void)
        {
        return(NumScans);
        }

// Functions associated with task profiling
void BaseTask::ActivateProfiling(double vbegin,double vend,int num_bins,int loglin)
    {
    if(num_bins <= 0)
        {
        // No bins -> No profiling
        profile_on = 0;
        return;
        }
    else
        {
        nbin = num_bins;
        v1 = vbegin;
        vlast = vend;
        nbin = num_bins;
        values = new double [nbin]; // Set up the values for the
            // frequency (histogram) boundaries
        occur = new long [nbin];  // One extra bin for >vlast

        int i;

        if(loglin)
            // 0 -> log; 1 -> linear intervals
            {
            // Linear intervals
            double add_amnt = (vlast - v1) / (nbin -2);
            for(values[0]= v1,i = 1;i < nbin-1; i++)
                {
                values[i] = values[i - 1] + add_amnt;
                }
            }
        else
            {
            // Log intervals
            double mult = exp(log(vlast / v1) / (nbin - 2));
            // Set up the boundaries for the time histogram
            for(values[0]= v1,i = 1;i < nbin-1; i++)
                {
                values[i] = values[i - 1] * mult;
                }
            }
        values[nbin-1] = 1.e20; // Big number
        for(i = 0; i < nbin; i++)occur[i] = 0;
        profile_on = 1;
        }
    }

void BaseTask::StartProfile(void)
    {
   if(!profile_on)return;
   Time0 = GetTimeNow();
   return;
   }

void BaseTask::EndProfile(void)
    {
   int j;
   double delt;

   if(!profile_on)return;
   delt = GetTimeNow() - Time0;

   for(j = 0; j < nbin; j++)
    {
      if(delt <= values[j])
        {
         occur[j]++;
         break;
         }
        }
   return;
   }

void BaseTask::WriteProfile(ofstream &OutputFile)
    {
   int i;

   if(!profile_on)
        {
        // Nothing to print
        OutputFile << "No profile statistics for this task\n";
        return;
        }
   for(i = 0; i < nbin - 1; i++)
        {
        OutputFile << "<" << values[i] << "\t\t" << occur[i] << "\n";
        }
    OutputFile << ">" << values[i-1] << "\t\t" << occur[i] << "\n";
   }

// BaseTask functions for message passing
// Delivery modes:
//  0  Only deliver message if message box is empty
//  1  Deliver message regardless of message box state

void BaseTask::SendMsg(BaseTask *ToTask,int BoxNo,int Flag,
                double Val,int mode,int ReturnReceipt)
    {
   int ReturnValue;
   int to_process = ToTask->GetTaskProcess();
   int this_task_code = this->GetTaskCode();

   if(to_process == ThisProcess)
    {
      // Message is local -- deliver it immediately
      ReturnValue = ToTask->AcceptMessage(BoxNo,Flag,Val,mode,
        TaskCode,ThisProcess);
      if(ReturnReceipt != -1)
        {
         // Send a return receipt
         SendRTMessage(this,ReturnReceipt,ReturnValue);  // The value
            // returned by Accept is sent as the flag to the return
            // mailbox, which is specified by the value of ReturnReceipt
         }
      }
   else
      {
      #ifdef USE_UDP
      int RetVal;
      int to_task_code = ToTask->GetTaskCode();

      RetVal = InsertMessage(to_process,to_task_code,BoxNo,ThisProcess,
        this_task_code,Flag,Val,ReturnReceipt,mode);
      if(RetVal)
        {
        // Error inserting message
        StopControl("<SendMsg> Error inserting message\n");
        return;
        }
      #else
      StopControl("<SendMsg> MultiProcess control not defined\n");
      return;
      #endif
      }
   }

// Two versions of SendRTMessage so to-task can be specified either by
//    pointer or by code
void BaseTask::SendRTMessage(BaseTask *ToTask,int BoxNo,int Flag,
                double Val,int mode,int ReturnReceipt)
    {
   SendMsg(ToTask,BoxNo,Flag,Val,mode,ReturnReceipt);
   }

void BaseTask::SendRTMessage(int ToTask,int BoxNo,int Flag,
                double Val,int mode,int ReturnReceipt)
    {
   SendMsg(TasksByCode[ToTask],BoxNo,Flag,Val,mode,ReturnReceipt);
   }


int BaseTask::GetRTMessage(int BoxNo,int *msg_flag,
         double *val, int *from_task,int *from_process)
   {
   /* Returns:
     -1 for error
      0 for no message available
      1 for successful retrieval
   */
   if((BoxNo >= NUM_MESSAGE_BOX) || (BoxNo < 0))return(-1); // Error
   CriticalSectionBegin();
   if(mbox[BoxNo].MessageAvailable == 0)
      {
      CriticalSectionEnd();
      return(0);  // No message available
      }
   // Get information
   if(msg_flag != NULL)*msg_flag = mbox[BoxNo].MessageFlag;
   if(val != NULL)*val = mbox[BoxNo].MessageValue;
   if(from_task != NULL)*from_task = mbox[BoxNo].FromTask;
   if(from_process != NULL)*from_process = mbox[BoxNo].FromProcess;
   mbox[BoxNo].MessageAvailable = 0;  // Clear message box
   CriticalSectionEnd();
   return(1);  // Success
   }

int BaseTask::AcceptMessage(int BoxNo,int msg_flag,double msg_val,int mode,
    int from_task,int from_process)
   {
   // Processes an incoming message
   // Returns 1 if message successfully delivered, 0 otherwise
   if((BoxNo >= NUM_MESSAGE_BOX) || (BoxNo < 0))return(0);
   if((mode < 0) || (mode > 1))
      {
      StopControl("Unknown message mode\n");
      return(0);
      }
   CriticalSectionBegin();
   if(mode == 0)
      {
      // Check to see if message box is empty
      if(mbox[BoxNo].MessageAvailable != 0)
         {
         CriticalSectionEnd();
         return(0);  // Can't deliver
         }
      }

   // Copy message information
   mbox[BoxNo].FromTask = from_task;
   mbox[BoxNo].FromProcess = from_process;
   mbox[BoxNo].MessageFlag = msg_flag;
   mbox[BoxNo].MessageValue = msg_val;
   mbox[BoxNo].MessageAvailable = 1;
   CriticalSectionEnd();
   return(1); // Successful delivery
   }

void BaseTask::SendCompletionMessage(int toTask,int &respBox,int code)
    {
    if(respBox >= 0)
        {
        SendRTMessage(toTask,respBox,code,0.0,MESSAGE_OVERWRITE);
        respBox = -1;  // Reset so accidental messages won't be sent
        }
    }

#ifdef USE_UDP  // Only compile for network applications
void StoreMessage(int ToProc,int ToTask,int BoxNo,int FromProc,
     int FromTask,int MsgFlag,double MsgValue,int RetRecpt,int DelMode)
    {
    // Store an incoming message into the task's message box
    int RetVal;

    if(ToProc != ThisProcess)
        {
        StopControl("<StoreMessage> Wrong process #.\n");
        return;
        }
    BaseTask *pTask = TasksByCode[ToTask];
    RetVal = pTask->AcceptMessage(BoxNo,MsgFlag,MsgValue,DelMode,
        FromTask,FromProc);
    if(RetRecpt != -1)
      {
       // Send a return receipt
       pTask->SendRTMessage(FromTask,RetRecpt,RetVal);  // The value
          // returned by Accept is sent as the flag to the return
          // mailbox, which is specified by the value of ReturnReceipt

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -