Pergunta

Estou tentando desenvolver um programa para limitar a execução de uma função. No código abaixo, tenho uma função chamada Inc que faz muitas iterações (simuladas pelo loop infinito). A primeira parte de cada iteração é bastante longa, seguida por uma segunda parte que deve ser muito rápida.

Não me importo de preencher a execução enquanto estiver na primeira parte do código, mas gostaria de evitar que o alarme sai ao fazer uma operação de gravação na segunda parte.

Minha primeira idéia foi desligar o alarme antes de entrar na 'região segura', economizando o tempo restante. Depois de sair, eu colocaria o alarme com o tempo economizado. Não sei como implementar isso. Alguém poderia me ajudar? Métodos alternativos também são bem -vindos.

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

pthread_t thread;
FILE *fout;

void *Inc(void *param){

    int i;
    long long int x = 0;

    fout = fopen("file.txt", "w");

    /* Large number of iterations */
    while(1){

        int k = 0;
        for(i=0; i<5000000; i++)
            k += (rand())%3;
        x += k;

        printf("%lld\n", x);
        /* Enter Safe Region */
        fprintf(fout, "%lld\n", x);
        /* Exit Safe Region */
    }   
}

void Finish(int param){
    pthread_cancel(thread);
    fclose(fout);
}

main (){

    pthread_attr_t attr;
    void *status;

    signal(SIGALRM, Finish);
    alarm(10);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&thread, &attr, Inc, NULL);
    pthread_attr_destroy(&attr);
    pthread_join(thread, &status);

    printf("Program Finished\n");
}
Foi útil?

Solução

O óbvio é pegar uma fechadura antes de ligar pthread_cancel, e manter a mesma fechadura em sua "região segura".

Infelizmente, você não pode esperar em um mutex ou um semáforo em um manipulador de sinal. Mas os sinais de alarme não são a única maneira de fazer algo depois de 10 segundos - você pode fazer com que seu tópico principal vá dormir por 10 segundos, depois acordar, pegar a fechadura, cancelar o thread do trabalhador e depois participar.

É claro que isso significaria que o fio principal dormirá 10 segundos, mesmo que o fio do trabalhador termine após 5 segundos. Então, em vez de dormir, peça ao tópico principal uma espera de 10 segundos cronometrados em um semáforo, que o fio do trabalhador publica quando terminar.

Como um sono, uma espera cronometrada pode ser concluída mais cedo devido a um sinal; portanto, tente novamente a espera cronometrada no eintr. Seus casos significativos são eintr (aguarde novamente), sucesso (junte -se ao thread do trabalhador - não há necessidade de cancelar, pois publicou o semáforo), Etimedout (pegue o bloqueio, cancele, junte -se) e, se quiser, outros erros. Não há outros erros listados para sem_timedwait Isso deve afetar você, no entanto.

Outra idéia é bloquear o Sigalrm em sua "região segura", o que seria mais simples, exceto que (a) nunca me lembro de como fazer E/S com segurança com sinais desativados e (b) o tópico do seu trabalhador provavelmente poderia estar executando "simultaneamente "Com o manipulador de sinal (verdadeiramente simultâneo ou aparentemente assim devido à pré-fixação), o que significa que o sinal pode ser tomado, seu trabalhador desativa os sinais e entra na região crítica, o manipulador de sinal o cancela. Se ninguém responde que realmente se lembra dos detalhes, aqui estão alguns Informações sobre sinais de bloqueio.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top