Created
August 20, 2015 03:18
-
-
Save marionette-of-u/5f108dbde25051db121c to your computer and use it in GitHub Desktop.
7年前にVC++2008で書いたtemplateベースの(OS系ではなくてゲーム技術系での)タスクシステム。もちろん現行の環境ではコンパイルエラー
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
軽量級タスクシステム | |
gccだと動かぬ | |
使い方は一番最後にあるよ | |
*/ | |
#ifndef __TTY_TASKSYSTEM__ | |
#define __TTY_TASKSYSTEM__ | |
#include <boost/preprocessor/repetition/repeat.hpp> | |
#include <boost/preprocessor/punctuation/comma_if.hpp> | |
#include <boost/preprocessor/arithmetic/inc.hpp> | |
#include <boost/preprocessor/arithmetic/dec.hpp> | |
#ifdef _MSC_VER | |
#pragma warning(disable:4503) | |
#endif | |
namespace tty{ | |
namespace tasksystem{ | |
namespace sst{ | |
//線形で保持する | |
#define LINE_LIMIT 127 | |
#define WRITE_LINE_TMPARG(z, i, nil) \ | |
BOOST_PP_COMMA_IF(i) typename T ## i = void | |
#define WRITE_LINE_SP(z, i, nil) \ | |
template<BOOST_PP_REPEAT(BOOST_PP_INC(i), WRITE_LINE_SP_I, nil)> \ | |
struct line<BOOST_PP_REPEAT(BOOST_PP_INC(i), WRITE_LINE_SP_II, nil)>{ \ | |
enum{ num = i }; \ | |
template<unsigned int a> struct typeholder; \ | |
BOOST_PP_REPEAT(BOOST_PP_INC(i), WRITE_LINE_SP_III, nil) \ | |
}; | |
#define WRITE_LINE_SP_I(z, i, nil) \ | |
BOOST_PP_COMMA_IF(i) typename T ## i | |
#define WRITE_LINE_SP_II(z, i, nil) \ | |
BOOST_PP_COMMA_IF(i) T ## i | |
#define WRITE_LINE_SP_III(z, i, nil) \ | |
template<> struct typeholder<i>{ typedef T ## i type; }; | |
template<BOOST_PP_REPEAT(LINE_LIMIT, WRITE_LINE_TMPARG, nil)> struct line{}; | |
BOOST_PP_REPEAT(BOOST_PP_DEC(LINE_LIMIT), WRITE_LINE_SP, nil) | |
#undef WRITE_LINE_SP | |
#undef WRITE_LINE_SP_I | |
#undef WRITE_LINE_SP_II | |
#undef WRITE_LINE_SP_III | |
#undef WRITE_LINE_TMPARG | |
#undef LINE_LIMIT | |
//下の様になる | |
//template<typename T0> | |
//struct line<T0>{ | |
// enum{ num = 1 }; | |
// template<unsigned int i> struct typeholder; | |
// template<> struct typeholder<0>{ typedef T0 type; }; | |
//}; | |
//template<typename T0, typename T1> | |
//struct line<T0, T1>{ | |
// enum{ num = 2 }; | |
// template<unsigned int i> struct typeholder; | |
// template<> struct typeholder<0>{ typedef T0 type; }; | |
// template<> struct typeholder<1>{ typedef T1 type; }; | |
//}; | |
//template<typename T0, typename T1, typename T2> | |
//struct line<T0, T1, T2>{ | |
// enum{ num = 3 }; | |
// template<unsigned int i> struct typeholder; | |
// template<> struct typeholder<0>{ typedef T0 type; }; | |
// template<> struct typeholder<1>{ typedef T1 type; }; | |
// template<> struct typeholder<2>{ typedef T2 type; }; | |
//}; | |
// : | |
// : | |
// : | |
//ネスト | |
template<typename T, typename L> | |
struct nest{ | |
typedef T type; | |
typedef L line; | |
}; | |
//タスク | |
template<typename T, unsigned int Num> | |
struct task{ | |
enum{ num = Num, wasize = sizeof(T) }; | |
typedef T type; | |
}; | |
} | |
//タスク型 | |
template<typename dammy_type> | |
struct xtask{ | |
typedef void (*fn_type)(xtask<void>*&); | |
xtask<void> *next, *prev; //次と前のタスク | |
void *wa; //ワーキングエリア | |
fn_type fn; //処理関数 | |
int spflag; //task : 0, begin : 1, end : 2 | |
}; | |
typedef xtask<void> task; | |
typedef task *&artask; | |
template<typename L> | |
class taskmain; | |
//メイン | |
template<typename L> | |
class taskmain{ | |
private: | |
task | |
xbegin_, | |
xend_, | |
*sysarray, | |
**taskarray; | |
char **workingarea; | |
//何もしない関数 | |
static void voidfn(artask){} | |
//型別にIDを振り分ける | |
static int id_(){ | |
static int i = 0; | |
return i++; | |
} | |
template<typename T> | |
static int id(){ | |
static int i = id_(); | |
return i; | |
} | |
//型操作など | |
//ネストされているかどうか | |
template<typename T> | |
struct nested_test; | |
template<typename T, unsigned int i> | |
struct nested_test< sst::task<T, i> >{ | |
typedef typename T type; | |
typedef void line; | |
}; | |
template<typename T, typename L> | |
struct nested_test< sst::nest<T, L> >{ | |
typedef typename T type; | |
typedef typename L line; | |
}; | |
//タスク型を取り除く | |
template<typename T> | |
struct distasktype{ | |
typedef T type; | |
}; | |
template<typename T, unsigned int i> | |
struct distasktype< sst::task<T, i> >{ | |
typedef T type; | |
}; | |
//ネスト型を取り除く | |
template<typename T> | |
struct disnesttype{ | |
typedef T type; | |
}; | |
template<typename T, typename U> | |
struct disnesttype< sst::nest<T, U> >{ | |
typedef T type; | |
}; | |
//選択的に生成 | |
template<typename T> | |
static void ctor_a_common( | |
task *sysa, | |
task **ta, | |
task &t, | |
char **wa, | |
int num | |
){ | |
int m = id<T>(); | |
if(num){ | |
int n = m * 3 + 2; | |
ta[m] = new task[num]; | |
wa[m] = new char[sizeof(T) * num]; | |
task *taa = ta[m]; | |
sysa[n].next = &taa[0]; | |
for(int i = 0, e = num - 1; i < e; ++i){ | |
taa[i].next = &taa[i + 1]; | |
} | |
taa[num - 1].next = &sysa[n]; | |
for(int i = 0; i < num; ++i){ | |
taa[i].wa = reinterpret_cast<void*>(&wa[m][sizeof(T) * i]); | |
} | |
}else{ | |
int n = m * 3 + 2; | |
sysa[n].next = sysa[n].prev = &sysa[n]; | |
ta[m] = reinterpret_cast<task*>(0); | |
wa[m] = reinterpret_cast<char*>(0); | |
} | |
int n = m * 3; | |
sysa[n].spflag = 1; | |
sysa[n].fn = voidfn; | |
t.next = &sysa[n]; | |
sysa[n].prev = &t; | |
} | |
template<typename T, unsigned int num> | |
struct ctor_a{ | |
inline static task &fn( | |
task *sysa, | |
task **ta, | |
char **wa, | |
task &t | |
){ | |
ctor_a_common<T>(sysa, ta, t, wa, num); | |
return sysa[id<T>() * 3]; | |
} | |
}; | |
template<typename T, unsigned int i, unsigned int num> | |
struct ctor_a<sst::task<T, i>, num>{ | |
inline static task &fn( | |
task *sysa, | |
task **ta, | |
char **wa, | |
task &t | |
){ | |
ctor_a_common<T>(sysa, ta, t, wa, num); | |
return sysa[id<T>() * 3]; | |
} | |
}; | |
template<typename T> | |
static void ctor_b_common(task *sysa, task &t){ | |
int m = id<T>() * 3 + 1; | |
sysa[m].spflag = 2; | |
sysa[m].fn = voidfn; | |
t.next = &sysa[m]; | |
sysa[m].next = &t; | |
} | |
template<typename T> | |
struct ctor_b{ | |
inline static task &fn(task *sysa, task &t){ | |
ctor_b_common<T>(sysa, t); | |
return sysa[id<T>() * 3 + 1]; | |
} | |
}; | |
template<typename T, unsigned int i> | |
struct ctor_b< sst::task<T, i> >{ | |
inline static task &fn(task *sysa, task &t){ | |
ctor_b_common<T>(sysa, t); | |
return sysa[id<T>() * 3 + 1]; | |
} | |
}; | |
//リストの各型を実体化する | |
template<typename L, unsigned int i = 0, bool b = false> | |
struct subst{ | |
typedef | |
subst< | |
typename nested_test< | |
typename L::typeholder<i>::type | |
>::line | |
> | |
base_a; | |
typedef subst<L, i + 1, L::num == i> base_b; | |
typedef typename L::typeholder<i>::type::type plntype; | |
typedef typename distasktype<plntype>::type objtype; | |
typedef typename L::typeholder<i>::type tplntype; | |
typedef typename disnesttype<tplntype>::type tasktype; | |
inline static int count(){ | |
return 1 + base_a::count() + base_b::count(); | |
} | |
inline static task &ctor( | |
task *sysa, | |
task **ta, | |
char **wa, | |
task &t | |
){ | |
return base_b::ctor( | |
sysa, ta, wa, | |
ctor_b<plntype>::fn( | |
sysa, | |
base_a::ctor( | |
sysa, ta, wa, | |
ctor_a< | |
plntype, | |
tasktype::num | |
>::fn(sysa, ta, wa, t) | |
) | |
) | |
); | |
} | |
}; | |
template<typename L, unsigned int i> | |
struct subst<L, i, true>{ | |
inline static int count(){ return 0;} | |
inline static task &ctor( | |
task *sysa, | |
task **ta, | |
char **wa, | |
task &t | |
){ return t; } | |
}; | |
template<> | |
struct subst<void, 0, false>{ | |
inline static int count(){ return 0;} | |
inline static task &ctor( | |
task *sysa, | |
task **ta, | |
char **wa, | |
task &t | |
){ return t; } | |
}; | |
//全て生成する | |
template<typename T, unsigned int num> | |
struct ctor_all_a{ | |
inline static taskmain &fn(taskmain &obj){ | |
for(unsigned int i = 0; i < num; ++i){ | |
obj.create_task<T>(); | |
} | |
return obj; | |
} | |
}; | |
template<typename T, unsigned int num> | |
struct ctor_all_a<sst::task<T, 0>, num>{ | |
inline static taskmain &fn(taskmain &obj){ | |
return obj; | |
} | |
}; | |
template<typename T, unsigned int i, unsigned int num> | |
struct ctor_all_a<sst::task<T, i>, num>{ | |
inline static taskmain &fn(taskmain &obj){ | |
for(unsigned int n = 0; n < i; ++n){ | |
obj.create_task<T>(); | |
} | |
return obj; | |
} | |
}; | |
template<typename T> | |
struct ctor_all_b{ | |
inline static taskmain &fn(taskmain &obj){ | |
obj.create_task<T>(); | |
return obj; | |
} | |
}; | |
template<typename T> | |
struct ctor_all_b< sst::task<T, 0> >{ | |
inline static taskmain &fn(taskmain &obj){ | |
return obj; | |
} | |
}; | |
template<typename T, unsigned int i> | |
struct ctor_all_b< sst::task<T, i> >{ | |
inline static taskmain &fn(taskmain &obj){ | |
for(unsigned int n = 0; n < i; ++n){ | |
obj.create_task<T>(); | |
} | |
return obj; | |
} | |
}; | |
template<typename La, unsigned int i = 0, bool b = false> | |
struct ctor_all{ | |
typedef | |
ctor_all< | |
typename nested_test< | |
typename La::typeholder<i>::type | |
>::line | |
> | |
base_a; | |
typedef ctor_all<La, i + 1, La::num == i> base_b; | |
typedef typename La::typeholder<i>::type::type plntype; | |
typedef typename distasktype<plntype>::type objtype; | |
typedef typename La::typeholder<i>::type tplntype; | |
typedef typename disnesttype<tplntype>::type tasktype; | |
inline static taskmain &ctor(taskmain &obj){ | |
base_b::ctor( | |
ctor_all_b<plntype>::fn( | |
base_a::ctor( | |
ctor_all_a< | |
plntype, | |
tasktype::num | |
>::fn(obj) | |
) | |
) | |
); | |
return obj; | |
} | |
}; | |
template<typename La, unsigned int i> | |
struct ctor_all<La, i, true>{ | |
inline static taskmain &ctor(taskmain &obj){ | |
return obj; | |
} | |
}; | |
template<> | |
struct ctor_all<void, 0, false>{ | |
inline static taskmain &ctor(taskmain &obj){ | |
return obj; | |
} | |
}; | |
public: | |
//幾つあるか | |
static int bcnum(){ | |
static int i = subst<L>::count(); | |
return i; | |
} | |
//タスクを生成する | |
template<typename T> | |
task *create_task(){ | |
int m = id<T>() * 3; | |
task *t = &sysarray[m + 2]; | |
if(t->next == t){ | |
return reinterpret_cast<task*>(0); | |
} | |
task *r = t->next; | |
t->next = r->next; | |
r->next = sysarray[m].next; | |
sysarray[m].next->prev = r; | |
r->prev = &sysarray[m]; | |
sysarray[m].next = r; | |
r->fn = T::fn; | |
r->spflag = 0; | |
new(r->wa) T; | |
return r; | |
} | |
//タスクを削除する | |
template<typename T> | |
task *delete_task(task *t){ | |
task *r = t->next; | |
reinterpret_cast<T*>(t->wa)->~T(); | |
t->prev->next = t->next; | |
t->next->prev = t->prev; | |
int m = id<T>() * 3 + 2; | |
t->next = sysarray[m].next; | |
sysarray[m].next = t; | |
return r; | |
} | |
//反復子みたいに | |
template<typename T> | |
task *begin(){ | |
return sysarray[id<T>() * 3].next; | |
} | |
template<typename T> | |
task *end(){ | |
return &sysarray[id<T>() * 3 + 1]; | |
} | |
task *xbegin(){ | |
return xbegin_.next; | |
} | |
task *xend(){ | |
return &xend_; | |
} | |
//タスクを回す | |
void operator()(){ | |
for( | |
task *t = xbegin(), *e = xend(); | |
t != e; | |
t = t->next | |
){ | |
(t->fn)(t); | |
} | |
} | |
//コンストラクタ/デストラクタ | |
taskmain(bool b = false){ | |
int n = bcnum(); | |
sysarray = new task[n * 3]; | |
taskarray = new task*[n]; | |
workingarea = new char*[n]; | |
sysarray[0].spflag = 1; | |
task &e( | |
subst<L>::ctor( | |
sysarray, | |
taskarray, | |
workingarea, | |
xbegin_ | |
) | |
); | |
e.next = &xend_; | |
xend_.prev = &e; | |
if(b){ | |
ctor_all<L>::ctor(*this); | |
} | |
} | |
virtual ~taskmain(){ | |
delete[] sysarray; | |
int n = bcnum(); | |
for(int i = 0; i < n; ++i){ | |
delete[] taskarray[i]; | |
delete[] workingarea[i]; | |
} | |
delete[] taskarray; | |
delete[] workingarea; | |
} | |
private: | |
taskmain(const taskmain&){} | |
}; | |
} | |
} | |
#endif // __TTY_TASKSYSTEM__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
template<typename T> | |
tty::tasksystem::task *create_task(); | |
template<typename T> | |
tty::tasksystem::task *delete_task(tty::tasksystem::artask); | |
struct a0{ | |
static void fn( | |
tty::tasksystem::artask t | |
){ | |
std::cout << "struct a0" << std::endl; | |
delete_task<a0>(t); | |
} | |
}; | |
struct a1{ | |
int i; | |
a1() : i(0){} | |
static void fn( | |
tty::tasksystem::artask t | |
){ | |
std::cout | |
<< "struct a1 " | |
<< reinterpret_cast<a1*>(t->wa)->i | |
<< std::endl; | |
++reinterpret_cast<a1*>(t->wa)->i; | |
create_task<a0>(); | |
} | |
}; | |
struct a2{}; | |
struct a3{ | |
int i; | |
a3() : i(0){} | |
static void fn( | |
tty::tasksystem::artask t | |
){ | |
std::cout | |
<< "struct a3 " | |
<< reinterpret_cast<a3*>(t->wa)->i | |
<< std::endl; | |
++reinterpret_cast<a3*>(t->wa)->i; | |
create_task<a1>(); | |
} | |
}; | |
struct a4{ | |
int i; | |
a4() : i(0){} | |
static void fn( | |
tty::tasksystem::artask t | |
){ | |
std::cout | |
<< "struct a4 " | |
<< reinterpret_cast<a4*>(t->wa)->i | |
<< std::endl; | |
++reinterpret_cast<a4*>(t->wa)->i; | |
create_task<a3>(); | |
} | |
}; | |
struct a5{ | |
int i; | |
a5() : i(0){} | |
static void fn( | |
tty::tasksystem::artask t | |
){ | |
std::cout | |
<< "struct a5 " | |
<< reinterpret_cast<a5*>(t->wa)->i | |
<< std::endl; | |
++reinterpret_cast<a5*>(t->wa)->i; | |
create_task<a4>(); | |
} | |
}; | |
namespace sst = tty::tasksystem::sst; | |
tty::tasksystem::taskmain< | |
sst::line< | |
sst::task<a0, 10>, | |
sst::task<a1, 10>, | |
sst::nest< | |
sst::task<a2, 0>, | |
sst::line< | |
sst::task<a3, 10>, | |
sst::task<a4, 10>, | |
sst::task<a5, 10> | |
> | |
> | |
> | |
> taskmain; | |
template<typename T> | |
tty::tasksystem::task *create_task(){ | |
return taskmain.create_task<T>(); | |
} | |
template<typename T> | |
tty::tasksystem::task *delete_task(tty::tasksystem::artask t){ | |
tty::tasksystem::task *a = t; | |
t = t->prev; | |
return taskmain.delete_task<T>(a); | |
} | |
int main(){ | |
taskmain.create_task<a5>(); | |
for(int i = 0; i < 6; ++i){ | |
std::cout << i << "--------" << std::endl; | |
taskmain(); | |
} | |
int n = 0; | |
for( | |
tty::tasksystem::task *t = taskmain.begin<a2>(); | |
t != taskmain.end<a2>(); | |
t = t->next | |
){ | |
if(t->spflag == 0) | |
++n; | |
} | |
std::cout | |
<< "a2で束ねられたタスクの数は" | |
<< n | |
<< "個です" | |
<< std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment