並行処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
マーチ

並行処理について

#1

投稿記事 by マーチ » 11年前

毎度毎度申し訳ございません。提出期限が既に2週間切れており、急いでいるため再び書き込ませていただきます。

下記の条件のプログラムを作成しております。
・スレッドはメッセージ表示、end入力、イベント送信の3つ
・入力したメッセージを3秒ごとに通常表示、逆から表示を交互にすること
・関数ポインタでメッセージ表示を交互に切り替えること

現在できない点は一つ
関数ポインタを使って切り替えて、メッセージを交互に表示させるということができません。

初心者ですが、何卒ご指摘助言よろしくお願いいたします。
コードを書き込ませていただきます。

コード:

#include <stdio.h>      
#include <string.h>     
#include <unistd.h>     
#include <pthread.h>    
#include <semaphore.h>  
 
//宣言
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag = PTHREAD_COND_INITIALIZER;

//構造体の宣言
struct Data {
    int timer;
    char message[256];
    // 関数ポインタ
    void (*print)(const char *msg); 
};
 
//そのまま表示
void normal_print(const char *msg)
{
    puts(msg);
}
 
//逆から表示
void reverse_print(const char *msg)
{
    //文字列長さ取得
    int n = strlen(msg);
    while (--n >= 0) putchar(msg[n]);
    putchar('\n');
}
// 関数ポインタ配列
void (*func[])() = { normal_print, reverse_print };
    
//イベント処理スレッド
void *timer_thread(void *arg)
{
    struct Data *pp = (struct Data *)arg;
    int i;
 
    //ポインタ演算子-> 左から右
    while (pp->timer) {
        // 3秒待ち
        for (i = 0; i < 3; i++) {  
	    // 1秒毎に終了チェック
            sleep(1);       
            if (!pp->timer) break;
        }
        // イベント送信
        pthread_cond_signal(&flag);
        
    }
    return NULL;
}
 
//表示スレッド
void *output_thread(void *arg)
{
    struct Data *pp = (struct Data *)arg;
 
    //printf("output_thread 開始");
    do {
	//メッセージ表示       
        int j=0;

        if(j % 2 == 0){
   	     printf( func[0]);
   	}
   	else{
	     printf( func[1]);
    	}
	j++;
        // イベント待ち 
        pthread_cond_wait(&flag, &lock);

        return 0;
    } 
    // 終了チェック
    while (pp->timer);  
    return NULL;
}
 
int main(void)
{
    struct Data data;
    pthread_t th1, th2;
    char buf[256], *p;
 
    printf("メッセージは何にしますか?\n");
    fgets(data.message, sizeof data.message, stdin);
    if ((p = strchr(data.message, '\n'))) *p = 0;
    printf("終了する場合はendを入力してください\n");

    data.timer = 1;
    //スレッド作成
    pthread_create(&th1, NULL, timer_thread, &data);
    pthread_create(&th2, NULL, output_thread, &data);
 
    //終了処理
    while (fgets(buf, sizeof buf, stdin) && strncmp(buf, "end", 3))
    printf("終了する場合はendを入力してください\n");
    data.timer = 0;
 
    //スレッドの破棄
    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    return 0;
}
教授の話によると、今回は2つだけだけどいっぱい作る場合を想定しろということで、
関数ポインタ配列を使った切り替えを一行で作れるからそうしろと言われ、全くできず・・・

どうかよろしくお願いいたします。

Poco
記事: 161
登録日時: 14年前

Re: 並行処理について

#2

投稿記事 by Poco » 11年前

マーチ さんが書きました:毎度毎度申し訳ございません。提出期限が既に2週間切れており、急いでいるため再び書き込ませていただきます。
(snip)
教授の話によると、今回は2つだけだけどいっぱい作る場合を想定しろということで、
関数ポインタ配列を使った切り替えを一行で作れるからそうしろと言われ、全くできず・・・

どうかよろしくお願いいたします。
単純にfunc()を呼び出す際の配列のインデックスをjを使って表せ、という意味では?
下のコードだと、切り替える関数が100個あったら、100個のif-else文ができそうな印象を与えますし。

コード:

    if(j % 2 == 0){
         printf( func[0]);
    }
    else{
         printf( func[1]);
    }
    j++;
↑を

コード:

func[jを使った式]();
j++
に変えるだけだと

かずま

Re: 並行処理について

#3

投稿記事 by かずま » 11年前

イベントって、条件変数(pthread_cond_t) のことだったんですね。

Windows なら、同期オブジェクトとして、ミューテックス、セマフォ、
そしてイベントがあるんですが、Linux にはイベントが無いということで、
セマフォや、ミューテックスを使う例を提示したんです。
条件変数も考えたんですが、ミューテックスも一緒に使わないといけないので
例として使うのをやめてしまいました。

みんながイベントって何のことだろうと悩んでいるのだから、分かった時点で
すぐに知らせてくれればよかったのに、と思います。

さて、新しいプログラムですが、do-while文のインデントが滅茶苦茶で
気分が悪くなってしまいます。

ループの中で int j = 0; を毎回実行したら、if文の else のほうは
絶対に通りません。

printf の第1引数は書式を表す文字列です。
ここに関数へのポインタを書いても意味がありません。

return 0; で、このスレッドは終了してしまいますよ。
メッセージをたった 1回表示しただけで。

ということで、次のように書けばよいはずです。

コード:

    int j = 0;
    do {
        func[j](pp->message); //メッセージ表示       
        j = !j;   // または j = 1 - j;
        pthread_cond_wait(&flag, &lock); // イベント待ち 
    } while (pp->timer);  // 終了チェック


マーチ

Re: 並行処理について

#4

投稿記事 by マーチ » 11年前

Pocoさん
返信ありがとうございます。
断片的なことばかり言われ理解の乏しい私はわからなくて・・・
ありがとうございます。


かずまさん
いつもいつもありがとうございます。
すみません、イベント関連は今日わかったもので・・・
インデントもすみません、気をつけます。

色々と滅茶苦茶ですね・・・書き直します。

マーチ

Re: 並行処理について

#5

投稿記事 by マーチ » 10年前

Pocoさん
もしかしたら勘違いされるかもと思い書きます。
断片的というのは教授が断片的なことばかりで理解できていないということです。
紛らわしくてすみません。

かずまさん
無事提出することが出来ました!ありがとうございました!
もしよろしければ今行っている課題の
http://dixq.net/forum/viewtopic.php?f=3&t=15659
もお時間があればご指摘助言お願いしたいです。よろしくお願いいたします。

閉鎖

“C言語何でも質問掲示板” へ戻る