タスクシステムを実装したコードを掘り当てたのでここに載せておきます。
多分Dのver2.59あたりじゃなかったかな、覚えてませんが。
C++との違いは、クラスの継承で生じるメモリの面倒な部分を考えなくて良い所。
C++では多重継承がかなり厄介で、そのあたりを考えるとちょっと複雑になりますが、
Dは元から多重継承がないのでラクですね。
最近はタスクシステムもワークエリアを動的に変える実装が流行りのようですが、
古式ゆかしい固定型で実装してました。
import std.stdio, std.string;
import std.c.string;
import rzGameCore;
//========================================================================
// タスクの根底構造
// 全ての動体はこのCMoverクラスを継承する
// そうしないとタスクリストで動かない
//========================================================================
class CMover {
protected:
uint Time = 0;
public:
void Draw(){}
bool Move(){return true;}
// タスクリストのメモリ上へインスタンスを生成
new(size_t t) {
void *p = Game.TaskList.Create().Memory.ptr;
return p;
}
// Moveがfalseを返したら削除
delete(void *p) {
// L.Remove(Id);
}
}
//========================================================================
// タスクリスト
//========================================================================
class CList {
protected:
//------------------------------------------------------------------------
// タスク
//------------------------------------------------------------------------
struct STask {
// 次タスクへのポインタ
STask *next;
// 前タスクへのポインタ
STask *prev;
// タスクID
int Id;
// ワークエリアメモリ
void[] Memory;
}
//------------------------------------------------------------------------
// メンバ変数
//------------------------------------------------------------------------
// 現在アクティブになってるタスクの数
uint NumActive = 0;
// タスクリストの長さ
int ListLength;
// ワークエリアメモリの最大サイズ
int WorkAreaMemorySize;
public:
//------------------------------------------------------------------------
// 外からアクセスできる変数
//------------------------------------------------------------------------
// 待機タスクリスト
STask[] Wait;
// 実行タスクリスト
STask *Active;
//======================================================================
// コンストラクタ
//======================================================================
this(in int list_length, in int work_area_size = 1024) {
ListLength = list_length;
WorkAreaMemorySize = work_area_size;
// メモリアライメントを計算
if(work_area_size % 8 != 0)
throw new Exception("wrong memory alignment");
//--------------------------------------------------------------------
// タスクリスト本体とタスクのワークエリアメモリを確保
//--------------------------------------------------------------------
Wait = new STask[list_length + 1];
for(int i = 0; i = NumActive) {
// 待機タスクを探して取り出す
STask *t = Wait.ptr.next;
t.prev.next = t.next;
t.next.prev = t.prev;
NumActive++;
// アクティブタスクへ挿入する
t.prev = Active.prev;
t.next = Active;
t.next.prev = t.prev.next = t;
return t;
}
return null;
} // end Create()
//======================================================================
// アクティブリストからタスクを取り出して待機リストへ繋ぐ
//======================================================================
void Remove(STask *t) {
if(NumActive >= 1) {
// アクティブタスクを取り出す
t.prev.next = t.next;
t.next.prev = t.prev;
// 待機タスクへ挿入する
t.prev = Wait.ptr;
t.next = Wait.ptr.next;
t.next.prev = t.prev.next = t;
NumActive--;
}
} // end Remove()
} // end CList