タスクシステムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Fimbul
記事: 100
登録日時: 12年前

タスクシステムについて

#1

投稿記事 by Fimbul » 12年前

コード:

#define TASK_MAX 200
#define ENM_MAX 100
#define ENM_SHOT_MAX 100

//タスクシステム?
int main() {
	Task* task[TASK_MAX];
	Enm* enm[ENM_MAX];
	EnmShot* enmShot[ENM_SHOT_MAX];
	//EnmクラスとEnmShotクラスはTaskクラスを継承したクラス
	
	//初期化
	for(int index = 0; index < TASK_MAX; index++) {
		task[index] = NULL;
	}
	for(int index = 0; index < ENM_MAX; index++) {
		enm[index] = NULL;
	}
	for(int index = 0; index < ENM_SHOT_MAX; index++) {
		enmShot[index] = NULL;
	}
	
	//何らかのきっかけでインスタンスを生成する
	for(int index = 0; index < ENM_MAX; index++) {
		if(enm[index] == NULL) {
			enm[index] = new Enm;
			break;
		}
	}
	for(int index = 0; index < ENM_SHOT_MAX; index++) {
		if(enmShot[index] == NULL) {
			enmShot[index] = new EnmShot;
			break;
		}
	}
	
	//タスクシステムに登録
	for(int index = 0; index < ENM_MAX; index++) {
		if(enm[index] != NULL) {
			for(int index_ = 0; index_ < TASK_MAX; index_++) {
				if(task[index_] == NULL) {
					task[index_] = enm[index];
					break;
				}
			}
			break;
		}
	}
	for(int index = 0; index < ENM_SHOT_MAX; index++) {
		if(enmShot[index] != NULL) {
			for(int index_ = 0; index_ < ENM_SHOT_MAX; index_++) {
				if(task[index_] == NULL) {
					task[index_] = enmShot[index];
					break;
				}
			}
			break;
		}
	}
	
	//何らかのきっかけで任意のタスクを削除、インスタンスも破棄する
	//インスタンスが登録されたタスクの番号を保持している必要がある
	task[インスタンスが登録されている番号] = NULL;
	delete enm[破棄したいインスタンスの番号];
	enm[破棄したいインスタンスの番号] = NULL;
	
	//タスクの実行
	//Calc()とDraw()はオーバーライドされた関数
	//この多態性を活かしたいのだと思う
	for(int index = 0; index < TASK_MAX; index++) {
		if(task[index] != NULL) {
			task[index]->Calc();
			task[index]->Draw();
		}
	}
	
	//インスタンスの破棄
	for(int index = 0; index < ENM_MAX; index++) {
		delete enm[index];
	}
	for(int index = 0; index < ENM_SHOT_MAX; index++) {
		delete enmShot[index];
	}
	
	return 0;
}
タスクを登録するリスト(タスクリスト? とします)は連結リストで可変長だと聞きました。
では、上記のコードの様に固定長のタスクリストはいけないんでしょうか。
そもそも、上記のコードがタスクシステムになっているかどうかが怪しいのですが・・・。

コードが長くなるので説明の簡単のために、Taskクラスのインスタンスを保持してタスクの登録と削除を行うTaskMgrクラスを定義せずに、上記の様にタスクの登録と削除をしています。

また、上記のコードはタスクを削除した後にタスクの整理(タスクの穴が出来ない様に、登録してあるタスクを前に詰める作業)をしていないので、タスクの実行時にタスクの最大登録数分ループしなければなりません。
そうではなく、タスクの整理をして次のタスクがヌルポインタかどうかを判断すれば、必要最小限でループが終了します。
ただ、タスクの最大登録数に依存すると思いますが、タスクの最大登録数分ループする時間とタスクを整理する時間の長さ、一般的にはどちらの処理の時間が短いのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: タスクシステムについて

#2

投稿記事 by softya(ソフト屋) » 12年前

結局のところリストにするのは全検索しないのでアクセス効率が良いからとリスト化することで優先順位ソート・マージが可能などのメリットが多いからです。
配列でも構わないのですが、「タスクの整理をして」と言うガベージコレクションをするならいっその事リストのほうがよくないかって話にはなると思います。

あと
Enm* enm[ENM_MAX];
EnmShot* enmShot[ENM_SHOT_MAX];
この2つの配列は不要では?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Fimbul
記事: 100
登録日時: 12年前

Re: タスクシステムについて

#3

投稿記事 by Fimbul » 12年前

softya(ソフト屋) さんが書きました: Enm* enm[ENM_MAX];
EnmShot* enmShot[ENM_SHOT_MAX];
この2つの配列は不要では?
以下の様に直しました。

コード:

#define TASK_MAX 200
 
//タスクシステム?
int main() {
    Task* task[TASK_MAX];
    
    //タスクリストの初期化
    for(int index = 0; index < TASK_MAX; index++) {
        task[index] = NULL;
    }
    
    //何らかのきっかけでインスタンスを生成、タスクリストに登録
    //EnmクラスとEnmShotクラスはTaskクラスを継承したクラス
    for(int index = 0; index < TASK_MAX; index++) {
    	if(task[index] != NULL) {
    		task[index] = new Enm;
    	}
    	break;
    }
    for(int index = 0; index < TASK_MAX; index++) {
    	if(task[index] != NULL) {
    		task[index] = new EnmShot;
    	}
    	break;
    }
    
    //何らかのきっかけで任意のタスクを削除、インスタンスも破棄する
    //インスタンスが登録されているタスクの番号を保持している必要がある
    delete task[削除したいタスクの番号];
    task[削除したいタスクの番号] = NULL;
    
    //タスクの実行
    //Calc()とDraw()はオーバーライドされた関数
    //この多態性を活かしたいのだと思う
    for(int index = 0; index < TASK_MAX; index++) {
        if(task[index] != NULL) {
            task[index]->Calc();
            task[index]->Draw();
        }
    }
    
    //インスタンスの破棄
    for(int index = 0; index < TASK_MAX; index++) {
        delete task[index];
    }
    
    return 0;
}
softya(ソフト屋) さんが書きました: 配列でも構わないのですが、「タスクの整理をして」と言うガベージコレクションをするならいっその事リストのほうがよくないかって話にはなると思います。
そうなんですか。
では、リストのタスクシステムと配列のタスクシステム(タスクの詰めをしない)でそんなに大きく効率は違うものなのでしょうか。
リストのタスクシステムを調べると、タスクの追加と削除の作業が煩わしく、そんなに効率が変わらないのなら配列のタスクシステムを使いたくなってしまいます。

また、忘れていたのですが、listクラステンプレートを使ってリストのタスクシステムを作る事は出来るのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: タスクシステムについて

#4

投稿記事 by softya(ソフト屋) » 12年前

Fimbul さんが書きました:では、リストのタスクシステムと配列のタスクシステム(タスクの詰めをしない)でそんなに大きく効率は違うものなのでしょうか。
リストのタスクシステムを調べると、タスクの追加と削除の作業が煩わしく、そんなに効率が変わらないのなら配列のタスクシステムを使いたくなってしまいます。
タスクシステムの場合実行順序の制御が必要になります。
これをどうやって実現するかですが結局リスト構造なようなものが必要になってくると思います。
色々やってみて実感して見ることが大事だと思いますので、まず実験してみては?
Fimbul さんが書きました:た、忘れていたのですが、listクラステンプレートを使ってリストのタスクシステムを作る事は出来るのでしょうか。
listクラスを使うことは可能です。まぁ、クラス化されたリスト構造って事です。
なので配列を止めてリスト構造にするって事になるのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

名前は開発中のものです。

Re: タスクシステムについて

#5

投稿記事 by 名前は開発中のものです。 » 12年前

C++を使っているなら std::vector, std::list などの標準コンテナを使えば簡単になるでしょう。配列・リストなどデータ構造の入れ替えも簡単になります。

そのうえで、効率については実測して判断すべきでしょう。挙げられた箇所についてはおそらく Calc(), Draw() の中のほうがはるかに重くなるのでどちらでも大差ないでしょうが。

Fimbul
記事: 100
登録日時: 12年前

Re: タスクシステムについて

#6

投稿記事 by Fimbul » 12年前

softya(ソフト屋) さんが書きました: listクラスを使うことは可能です。まぁ、クラス化されたリスト構造って事です。
なので配列を止めてリスト構造にするって事になるのでは?
そうなりますね。
softya(ソフト屋) さんが書きました: タスクシステムの場合実行順序の制御が必要になります。
これをどうやって実現するかですが結局リスト構造なようなものが必要になってくると思います。
色々やってみて実感して見ることが大事だと思いますので、まず実験してみては?
実行順序の制御がなぜ必要か分からないので、色々試して再度分からない所が出てきたら質問する事にします。

softyaさん、名前は開発中のものです。さん、ありがとうございました。

閉鎖

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