-2 votes

Multitâche : comment faire en sorte que le fil de travail prenne le contrôle après avoir appelé une fonction de boucle infinie ?

Supposons que l'on crée 3 threads de travail par pthread_create,

dans ces routines de fils de travail, chacun appelle une fonction de boucle infinie simple qui n'a pas de retour pour faire le comptage.

comment faire en sorte que le fil de travail prenne le contrôle après avoir appelé la fonction de boucle infinie et sauvegarder le contexte de la fonction de boucle infinie pour l'appeler à nouveau dans le fil de travail ?

0voto

Peter Tillemans Points 20129

Laissez-moi reformuler pour voir si j'ai bien compris le problème.

Vous avez un thread maître qui génère 3 threads ouvriers qui effectuent chacun un travail de longue durée (infini).

À un certain moment, vous voulez interrompre le traitement, sauvegarder l'état de tous les threads pour qu'ils reprennent là où ils en étaient restés à un moment ultérieur.

Je pense que le meilleur moyen d'y parvenir est d'organiser le travail de vos fils en morceaux liés à des transactions. Lors du redémarrage, vous vérifiez la dernière transaction terminée, et vous partez de là.

Mais puisque je soupçonne qu'il s'agit d'un devoir à domicile sur la plomberie des fils de bas niveau, puis-je suggérer un booléen partagé qui est vérifié à chaque fois que vous passez par la boucle pour sortir et stocker l'état après. Une autre solution consiste à "tuer" le thread, à attraper l'exception et à stocker l'état. La dernière option est désordonnée.

0voto

user353573 Points 15

Je veux faire l'effet d'un pool de threads, après avoir appelé la fonction de boucle infinie, chaque thread de travail peut changer d'autres tâches (autre fonction de boucle infinie) pour les exécuter.

Par exemple, 3 fils de travail peuvent exécuter 4 tâches (fonctions de boucle infinie).

#ifndef JOB_CPP
#define JOB_CPP

#include "job.h"

#define NUM_OF_TASKS 4
#define NUM_OF_WORKERS 3
    void (* job_queue[NUM_OF_TASKS])(void*);
    void (* fp[NUM_OF_WORKERS])(void*); // original running job
    int running_task[NUM_OF_WORKERS];
    int idle[NUM_OF_TASKS];
    int last_running_task[NUM_OF_WORKERS];
    int no_of_tasks_running[NUM_OF_WORKERS];
    my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};

void func1(void *arg)
{
    int count = 0;
    int status;
    while(true)
    {
        //if((count % 100) == 0)
        //printf("func1 run %d\n", count);
        count = count + 1;
        //status = pthread_cond_signal(&data.cv);
    }
}
void func2(void *arg)
{
    int count = 0;
    int status;
    while(true)
    {
        //printf("func2 run %d\n", count);
        count = count + 1;
        //status = pthread_cond_signal(&data.cv);
    }
}
void func3(void *arg)
{   int count = 0;
    int status;
    while(true)
    {
        //printf("func3 run %d\n", count);
        count = count + 1;
        //status = pthread_cond_signal(&data.cv);
    }
}
void func4(void *arg)
{   int count = 0;
    int status;
    while(true)
    {
        //printf("func4 run %d\n", count);
        count = count + 1;
        //status = pthread_cond_signal(&data.done);
    }
}

void jobinit()
{
    for(int i=0; i<NUM_OF_TASKS; i++)
    {
        job_queue[i] = NULL;
        idle[i] = 0;
    }
    for(int i=0; i<NUM_OF_WORKERS; i++)
    {
        fp[i] = NULL;
        running_task[i] = 0;
        last_running_task[i] = 0;
        no_of_tasks_running[i] = 0;
    }
    jobadd(func1);
    jobadd(func2);
    jobadd(func3);
    jobadd(func4);
    jobrun();
}
void jobadd(void (*job)(void*))
{   
    for(int i=0; i<4; i++)
    {
        if(job_queue[i] == NULL)
        {
            job_queue[i] = job;
            return;
        }
    }
}
void* workserver(void *arg);
void* workserver(void *arg)
{
    int status, timedout;

    struct timespec timeout;

    status = pthread_mutex_lock(&data.mutex);
    while(true)
    {
        timedout = 0;   
        clock_gettime(CLOCK_REALTIME, &timeout);
        timeout.tv_sec += 2;

        sleep(1);
        //void (* clean)(void*);

        status = pthread_cond_timedwait(&data.cv, &data.mutex, &timeout);
        if(status == ETIMEDOUT){
            printf("worker wait timed out %d\n", (int)arg);
            timedout = 1;
        }else if(status != 0){
            printf("worker wait failed %d\n", (int)arg);
            status = pthread_mutex_unlock(&data.mutex);
            return NULL;
        }
        printf("workserver number: %d\n", (int)arg);

        status = pthread_mutex_unlock(&data.mutex);     

        printf("function run %d\n", (int)arg);
        (* job_queue[(int)arg])(NULL);

        printf("cond wait start %d\n", (int)arg);
        status = pthread_cond_wait(&data.done, &data.mutex);
        printf("cond wait end\n");

        status = pthread_mutex_lock(&data.mutex);
    }
}
void jobrun() 
{   
    for(int i=0; i<3; i++) {idle[i] = 0;}
    pthread_t r1_threadid[3];

    for(int i=0; i<3; i++)  
    {
        pthread_create(&r1_threadid[i], NULL, workserver, (void*)i);
    }

    int status;
    struct timespec timeout;

    timeout.tv_sec = time (NULL) + 2;
    timeout.tv_nsec = 0;

    while(true)
    {
    status = pthread_mutex_lock(&data.mutex);
    while(data.value == 0)
    {
        status = pthread_cond_timedwait(&data.cond, &data.mutex, &timeout);
    }
    if(data.value != 0)
    {
        //printf("condition was signaled\n");
        data.value = 0;
    }
    status = pthread_mutex_unlock(&data.mutex);
    if(status != 0)
        printf("unlock mutex error");
    }
}
#endif

0voto

Jim Dennis Points 5454

Je pense que vous devriez clarifier votre question.

Si chaque thread de travail appelle une boucle infinie, je suppose que votre thread maître devrait appeler pthread_cancel() sur chacun d'eux. D'après ce que je comprends, cela pourrait nécessiter des appels à d'autres pthread_*() pour définir le caractère "annulable" des fils cibles.

Bien sûr, cette suggestion soulève la question. L'approche largement préférable serait d'empêcher ces boucles infinies. Écrivez votre code de façon à ce qu'il ait des conditions de sortie... de façon à ce que le travail soit limité par une entrée ou un traitement d'événement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X