Cómo utilizar la ayuda multitarea c
En algunos sistemas, es necesario crear su propio marco de trabajo multitarea asíncrono. Con este tipo de multitarea, usted mismo puede implementar una pequeña parte del modelo de programación basada en eventos. Por supuesto, el evento impulsado es bueno para las computadoras, pero no para los seres humanos. Si una persona está impulsada por eventos, o es bombero o es un fracaso, jaja. Además, cuando existe una situación típica de bucle "esperando datos-gt; procesando datos-gt; esperando datos", el uso del procesamiento asincrónico puede aumentar en gran medida el rendimiento del sistema, especialmente cuando los datos y el procesamiento son interdependientes. Por ejemplo: los datos de salida de la tarea A son la entrada de la tarea B y la salida de B es la entrada de C. Además, B y C necesitan dedicar mucho tiempo a la inicialización antes de que el procesamiento lineal obviamente tenga una. cuello de botella en el rendimiento. El uso del procesamiento asincrónico puede mejorar esta situación y el rendimiento mejorará enormemente cuando haya varios procesadores.
La multitarea asincrónica descrita en este artículo utiliza el programador en el mismo proceso para programar múltiples tareas asincrónicas en el proceso. La ejecución real de estas tareas asincrónicas se completa a través de subprocesos de trabajo. El modelo es: cada tarea asincrónica se bloquea después de enviar una solicitud, cuando se completa la tarea solicitada, el programador activa la tarea y realiza el procesamiento correspondiente (tal vez enviando una solicitud nuevamente). Este es un problema típico de productor/consumidor: en el programador, el productor es la tarea y el programador es el consumidor. Una vez que se completa la solicitud de la tarea, el programador ejecuta la tarea.
Proceso de procesamiento
Dado que el programador está en un proceso, primero debe instalar el programador en el proceso y luego agregar cada tarea asincrónica al programador. La tarea envía la primera. Una solicitud está esperando ser completada. Finalmente, inicie el programador para procesar cada solicitud completa. Como se muestra en la siguiente figura:
Tareas
Cada tarea debe heredar de la misma clase base para que el programador pueda manejarlas de la misma manera. Cada tarea derivada debe contener (al menos) una operación asincrónica (o su propio objeto), que se puede ejecutar de 1 a n veces. Una vez completada cada operación asincrónica, se llamará a su función Run() para su procesamiento posterior. Por lo tanto, una tarea debe tener al menos un miembro de estado que indique el estado de la tarea. Cuando se procesa la tarea, la tarea puede eliminarse de la cola de programación. Dado que la adición de una tarea a la cola de programación debe ser realizada por el programador en lugar de la tarea en sí, la operación Add() no es necesaria.
Por lo tanto, la clase de tarea debería verse así:
Entre ellas:
StartWorker() y Dequeue() son implementadas por TaskBase:
int TaskBase: : Dequeue()
{
Programador* sched = SchedulerInstance::GetInstance()
int ret = ErrNone
m_Mutex; - gt;Lock();
if (sched amp; amp; m_Status != TaskPending)
sched-gt;Remove(this);
else
ret = ErrTaskBusy
m_Mutex-gt; Desbloquear()
devolver
}
int TaskBase::StartWorker()
{
Programador* sched = SchedulerInstance::GetInstance();
int ret = ErrNone;
m_Mutex-gt;Lock();
if (sched amp; amp; (m_Status != TaskPending || m_Status != NotAvailable))
{
m_Worker-gt; RunThread(este);
}
else
ret = ErrTaskBusy
m_Mutex-gt; Desbloquear ();
return ret;
}
void TaskBase::CancelWorker()
{
Programador* sched = SchedulerInstance::GetInstance();
m_Mutex-gt;
if (programado amp; amp; m_Status == TaskPending)
{
m_Worker-gt;Cancelar();
m_Status = TareaCancelada;
}
m_Mutex-gt;Desbloquear ( );
}
Dado que un subproceso de trabajo se utiliza para realizar operaciones asincrónicas verdaderas, debe haber una función estática como función de entrada del subproceso.
Se implementa como:
void WorkerThread::ThreadFunction(void* aData)
{
TaskBase* task = static_castlt; TaskBase *gt; (aData);
if (tarea)
task-gt; IssueRequest()
// Notificar al programador
Programador* sched = SchedulerInstance::GetInstance();
if (sched)
sched-gt();
} p >
Dado que la implementación de subprocesos de trabajo depende de la plataforma, la implementación típica de la plataforma Linux se enumera aquí:
void LinuxThread::RunThread(void* aData)
{
pthread_create(amp;m_TID, NULL, WorkerThread::ThreadFunction, aData);
Programador* sched = SchedulerInstance::GetInstance();
if (sched )
sched-gt;Notify();
}
void LinuxThread::Cancel()
{
pthread_cancel(m_TID);
Programador* sched = SchedulerInstance::GetInstance();
if (programado)
sched-gt ; Notificar( );
}