0

独自の stop_watch モジュールを作成しました。これにより、スレッドが作成され、数秒間スリープ状態になります。秒が経過すると、main.c でコールバック関数が呼び出され、ユーザーに時間が経過したことが通知されます。

これは、ユーザーが数字を入力するのに 3 秒しか与えられず、5 桁を入力する必要があるようにするためです。期限が切れた場合、プログラムは停止する必要があります。

2つの問題。1) 所要時間内に数字を入力した場合。スレッドをキャンセルするにはどうすればよいですか。thread_kill または thread_cancel を使用することを考えていましたか? 2) do_while ループで終了するにはどうすればよいですか? ユーザーが入力するのを待っている間、scanfはブロックします。

ご提案いただきありがとうございます。

以下の私のコード:

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

#include "stop_watch.h"

struct data_struct *g_data_struct;

void timeout_cb(int id)
{
    printf("Digit timeout\n");
    free(g_data_struct);
}

int main()
{
    pthread_t thread_id;
    unsigned int digit = 0;

    g_data_struct = (struct data_struct*) calloc(1, sizeof(*g_data_struct));

    if(!g_data_struct)
    {
        printf("=== failed to allocate memory ===\n");
        return 0;
    }

    /* start timer for 3 seconds */
    g_data_struct->seconds = 3;
    g_data_struct->func_ptr = timeout_cb;
    thread_id = start_stopwatch(g_data_struct);

    do
    {
        printf("Enter digit: ");
        scanf("%d", &digit);
    }while(1);

    pthread_join(thread_id, NULL);
    printf("=== End of Program - all threads in ===\n");

    free(g_data_struct);

    return 0;
}



#include <stdio.h>
#include <pthread.h>

#include "stop_watch.h"

pthread_t thread_id;
static id = 10;

/* start sleeping and call the callback when seconds have expired */
static void* g_start_timer(void *args)
{
    void (*function_pointer)(int id);
    int seconds = ((struct data_struct*) args)->seconds;
    function_pointer = ((struct data_struct*) args)->func_ptr;

    sleep(seconds);

    (void) (*function_pointer)(id);

    pthread_exit(NULL);

    return 0;
}

/* Will sleep in its own thread for a period of seconds */
int start_stopwatch(struct data_struct *g_data_struct)
{
    int rc = 0;

    int seconds = g_data_struct->seconds;
    printf("=== start_stopwatch(): %d\n", seconds);

    rc =  pthread_create(&thread_id, NULL, g_start_timer, (void *) g_data_struct);

    if(rc)
    {    
        printf("=== Failed to create thread\n");
        return 1;
    }

    return thread_id;
}

ちなみに、この質問はC99 gccに関するものです。

4

2 に答える 2

2

そもそもこれに別のスレッドを使用することはお勧めしません。でも、糸の使い方を覚える練習になりそうなので、やってみます。

数字が入力されたかどうかを示すグローバルブールフラグを設定できます。g_start_timer では、function_pointer を呼び出す直前に、フラグが設定されているかどうかを確認します。その場合は、関数を呼び出さないでください。

スリープ期間が終了する前にスレッドを早く終了させたい場合は、try ロックでミューテックスを使用できます。

編集:あなたはそれが演習ではないと言うので、私はそれをどのように行うかについて言及します. select() や poll() など、stdin での入力の待機中にタイムアウトになる可能性がある関数を使用します。または、alarm() を使用して中断します。アラームの使用例を次に示します。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

void alarm_signal(int signum)
{
}

int main()
{
    char c;
    unsigned int v = 0;
    struct sigaction act;
    puts("Enter digit: ");

    /* Register dummy handler for alarm */
    act.sa_handler = &alarm_signal;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGALRM, &act, NULL);

    /* Set timer for 3 seconds */
    alarm(3);

    /* Read the digits */
    errno = 0;
    while(0 != read(STDIN_FILENO, &c, 1))
    {
        if(c < '0' || c > '9')
            break;
        v = v*10 + c - '0';
    }
    if(errno == EINTR)
        puts("Timed out");
    else
        printf("Value is %d\n", v);
    return 0;
}
于 2009-03-04T21:17:11.010 に答える
1

もちろん、thread_cancel を使用してスレッドをキャンセルできます。scanf に関しては、パイプを使用して端末からの入力をシミュレートすることを考えるかもしれません。

于 2009-12-19T06:32:13.967 に答える