Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Created August 20, 2015 03:18
Show Gist options
  • Save marionette-of-u/5f108dbde25051db121c to your computer and use it in GitHub Desktop.
Save marionette-of-u/5f108dbde25051db121c to your computer and use it in GitHub Desktop.
7年前にVC++2008で書いたtemplateベースの(OS系ではなくてゲーム技術系での)タスクシステム。もちろん現行の環境ではコンパイルエラー
/*
軽量級タスクシステム
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__
#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