From c101d0da231532468641a62fc188cc0a8fe98fc0 Mon Sep 17 00:00:00 2001 From: cxl Date: Mon, 17 Mar 2014 18:05:55 +0000 Subject: [PATCH] Core: rudimentary Callback lambda support git-svn-id: svn://ultimatepp.org/upp/trunk@7051 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CbGen/CbGen.upp | 2 +- uppsrc/CbGen/CppGen.cpp | 36 ++++++- uppsrc/Core/Cbgen.h | 134 +++++++++++++++++++++++- uppsrc/Core/src.tpp/Callbacks$en-us.tpp | 9 ++ 4 files changed, 178 insertions(+), 3 deletions(-) diff --git a/uppsrc/CbGen/CbGen.upp b/uppsrc/CbGen/CbGen.upp index a081d7ea3..b50c992a3 100644 --- a/uppsrc/CbGen/CbGen.upp +++ b/uppsrc/CbGen/CbGen.upp @@ -1,4 +1,4 @@ -description "Utility to generate (long and repetitive) callback C++ source files"; +description "Utility to generate (long and repetitive) callback C++ source files\377"; uses Core; diff --git a/uppsrc/CbGen/CppGen.cpp b/uppsrc/CbGen/CppGen.cpp index 654a9353b..3ab7afa2b 100644 --- a/uppsrc/CbGen/CppGen.cpp +++ b/uppsrc/CbGen/CppGen.cpp @@ -7,6 +7,12 @@ String If(String s, String txt) return IsNull(s) ? String() : txt; } +/* +#ifdef CPP_11 + Callback& operator=(const std::function& fn) { Release(); action = new LambdaCallbackAction(fn); return *this; } +#endif +*/ + void CallbackGen(String name, String rettype, int n, String extension, String atest = Null) { LOG("// -----------------------------------------------------------"); @@ -24,7 +30,7 @@ void CallbackGen(String name, String rettype, int n, String extension, String at paramlist << Format("p%d", i); } String cl_list = If(classlist, "<" + classlist + ">"); - String cl_temp = String("template "; + String cl_temp = String("template "; String return_ = rettype == "void" ? "" : "return "; String name_cl = name + cl_list; LOG(""); @@ -45,6 +51,24 @@ void CallbackGen(String name, String rettype, int n, String extension, String at LOG("};"); LOG(""); + LOG("#ifdef HAS_LAMBDA"); + if(!IsNull(classdef)) + LOG("template <" << classdef << ">"); + LOG("struct Lambda" << name << " : public " << name << "Action" << cl_list + " {"); + LOGBEGIN(); + LOG("std::function<" << rettype << " (" << classlist << ")> fn;"); + if(rettype == "void") + LOG("virtual void Execute(" << paramdef << ") { fn(" << paramlist << "); }"); + else + LOG("virtual " << rettype << " Execute(" << paramdef << ") { return fn(" << paramlist << "); }"); + LOG(""); + LOG("Lambda" << name << "(std::function<" << rettype << " (" << classlist << ")> fn) : fn(fn) {}"); + LOGEND(); + LOG("};"); + LOG("#endif"); + LOG(""); + +#if 0 LOG(cl_temp); LOG("struct " << name << "MethodActionPte : public " << name << "Action" << cl_list + " {"); LOGBEGIN(); @@ -121,6 +145,7 @@ void CallbackGen(String name, String rettype, int n, String extension, String at LOGEND(); LOG("};"); LOG(""); +#endif if(!IsNull(classdef)) LOG("template <" << classdef << ">"); @@ -154,6 +179,13 @@ void CallbackGen(String name, String rettype, int n, String extension, String at LOG(name << "() { action = NULL; }"); LOG(name << "(_CNULL) { action = NULL; }"); LOG("~" << name << "();"); + LOGEND(); + LOG("#ifdef HAS_LAMBDA"); + LOGBEGIN(); + LOG(name << "& operator=(std::function<" << rettype << " (" << classlist << ")> l) { Clear(); action = new Lambda" << name << "<" << classlist << ">(l); return *this; }"); + LOGEND(); + LOG("#endif"); + LOGBEGIN(); LOG(""); LOG("static " << name << " Empty() { return CNULL; }"); LOG(""); @@ -165,6 +197,7 @@ void CallbackGen(String name, String rettype, int n, String extension, String at LOG("};"); LOG(""); +#if 0 LOG(cl_temp); LOG(name_cl << " pteback(OBJECT *object, " << rettype << " (METHOD::*method)(" << paramdef << ")) {"); @@ -290,6 +323,7 @@ void CallbackGen(String name, String rettype, int n, String extension, String at LOG("#ifndef CPP_PART__"); LOG(""); } +#endif }; CONSOLE_APP_MAIN diff --git a/uppsrc/Core/Cbgen.h b/uppsrc/Core/Cbgen.h index 1e6c1d34f..87c4ceeaf 100644 --- a/uppsrc/Core/Cbgen.h +++ b/uppsrc/Core/Cbgen.h @@ -1,5 +1,9 @@ // ----------------------------------------------------------- +#ifdef CPP_11 +#define HAS_LAMBDA 1 +#endif + struct CallbackAction { Atomic count; @@ -10,6 +14,15 @@ struct CallbackAction { virtual ~CallbackAction() {} }; +#ifdef HAS_LAMBDA +struct LambdaCallback : CallbackAction { + std::function fn; + virtual void Execute() { fn(); } + + LambdaCallback(std::function fn) : fn(fn) {} +}; +#endif + class Callback : Moveable< Callback > { CallbackAction *action; @@ -34,10 +47,13 @@ public: explicit Callback(CallbackAction *newaction) { action = newaction; } Callback() { action = NULL; } Callback(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Callback& operator=(std::function l) { Clear(); action = new LambdaCallback(l); return *this; } +#endif + ~Callback(); static Callback Empty() { return CNULL; } - }; // ----------------------------------------------------------- @@ -53,6 +69,16 @@ struct Callback1Action { virtual ~Callback1Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaCallback1 : public Callback1Action { + std::function fn; + virtual void Execute(P1 p1) { fn(p1); } + + LambdaCallback1(std::function fn) : fn(fn) {} +}; +#endif + template class Callback1 : Moveable< Callback1 > { Callback1Action *action; @@ -79,6 +105,9 @@ public: Callback1() { action = NULL; } Callback1(_CNULL) { action = NULL; } ~Callback1(); +#ifdef HAS_LAMBDA + Callback1& operator=(std::function l) { Clear(); action = new LambdaCallback1(l); return *this; } +#endif static Callback1 Empty() { return CNULL; } @@ -119,6 +148,16 @@ struct Callback2Action { virtual ~Callback2Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaCallback2 : public Callback2Action { + std::function fn; + virtual void Execute(P1 p1, P2 p2) { fn(p1, p2); } + + LambdaCallback2(std::function fn) : fn(fn) {} +}; +#endif + template class Callback2 : Moveable< Callback2 > { Callback2Action *action; @@ -144,6 +183,9 @@ public: explicit Callback2(Callback2Action *newaction) { action = newaction; } Callback2() { action = NULL; } Callback2(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Callback2& operator=(std::function l) { Clear(); action = new LambdaCallback2(l); return *this; } +#endif ~Callback2(); static Callback2 Empty() { return CNULL; } @@ -185,6 +227,16 @@ struct Callback3Action { virtual ~Callback3Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaCallback3 : public Callback3Action { + std::function fn; + virtual void Execute(P1 p1, P2 p2, P3 p3) { fn(p1, p2, p3); } + + LambdaCallback3(std::function fn) : fn(fn) {} +}; +#endif + template class Callback3 : Moveable< Callback3 > { Callback3Action *action; @@ -210,6 +262,9 @@ public: explicit Callback3(Callback3Action *newaction) { action = newaction; } Callback3() { action = NULL; } Callback3(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Callback3& operator=(std::function l) { Clear(); action = new LambdaCallback3(l); return *this; } +#endif ~Callback3(); static Callback3 Empty() { return CNULL; } @@ -251,6 +306,16 @@ struct Callback4Action { virtual ~Callback4Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaCallback4 : public Callback4Action { + std::function fn; + virtual void Execute(P1 p1, P2 p2, P3 p3, P4 p4) { fn(p1, p2, p3, p4); } + + LambdaCallback4(std::function fn) : fn(fn) {} +}; +#endif + template class Callback4 : Moveable< Callback4 > { Callback4Action *action; @@ -276,6 +341,9 @@ public: explicit Callback4(Callback4Action *newaction) { action = newaction; } Callback4() { action = NULL; } Callback4(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Callback4& operator=(std::function l) { Clear(); action = new LambdaCallback4(l); return *this; } +#endif ~Callback4(); static Callback4 Empty() { return CNULL; } @@ -316,6 +384,15 @@ struct GateAction { virtual ~GateAction() {} }; +#ifdef HAS_LAMBDA +struct LambdaGate : public GateAction { + std::function fn; + virtual bool Execute() { return fn(); } + + LambdaGate(std::function fn) : fn(fn) {} +}; +#endif + class Gate : Moveable< Gate > { GateAction *action; @@ -346,6 +423,9 @@ public: explicit Gate(GateAction *newaction) { action = newaction; } Gate() { action = NULL; } Gate(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Gate& operator=(std::function l) { Clear(); action = new LambdaGate(l); return *this; } +#endif ~Gate(); static Gate Empty() { return CNULL; } @@ -365,6 +445,16 @@ struct Gate1Action { virtual ~Gate1Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaGate1 : public Gate1Action { + std::function fn; + virtual bool Execute(P1 p1) { return fn(p1); } + + LambdaGate1(std::function fn) : fn(fn) {} +}; +#endif + template class Gate1 : Moveable< Gate1 > { Gate1Action *action; @@ -397,6 +487,9 @@ public: explicit Gate1(Gate1Action *newaction) { action = newaction; } Gate1() { action = NULL; } Gate1(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Gate1& operator=(std::function l) { Clear(); action = new LambdaGate1(l); return *this; } +#endif ~Gate1(); static Gate1 Empty() { return CNULL; } @@ -438,6 +531,16 @@ struct Gate2Action { virtual ~Gate2Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaGate2 : public Gate2Action { + std::function fn; + virtual bool Execute(P1 p1, P2 p2) { return fn(p1, p2); } + + LambdaGate2(std::function fn) : fn(fn) {} +}; +#endif + template class Gate2 : Moveable< Gate2 > { Gate2Action *action; @@ -469,6 +572,9 @@ public: explicit Gate2(Gate2Action *newaction) { action = newaction; } Gate2() { action = NULL; } Gate2(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Gate2& operator=(std::function l) { Clear(); action = new LambdaGate2(l); return *this; } +#endif ~Gate2(); static Gate2 Empty() { return CNULL; } @@ -510,6 +616,16 @@ struct Gate3Action { virtual ~Gate3Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaGate3 : public Gate3Action { + std::function fn; + virtual bool Execute(P1 p1, P2 p2, P3 p3) { return fn(p1, p2, p3); } + + LambdaGate3(std::function fn) : fn(fn) {} +}; +#endif + template class Gate3 : Moveable< Gate3 > { Gate3Action *action; @@ -541,6 +657,9 @@ public: explicit Gate3(Gate3Action *newaction) { action = newaction; } Gate3() { action = NULL; } Gate3(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Gate3& operator=(std::function l) { Clear(); action = new LambdaGate3(l); return *this; } +#endif ~Gate3(); static Gate3 Empty() { return CNULL; } @@ -582,6 +701,16 @@ struct Gate4Action { virtual ~Gate4Action() {} }; +#ifdef HAS_LAMBDA +template +struct LambdaGate4 : public Gate4Action { + std::function fn; + virtual bool Execute(P1 p1, P2 p2, P3 p3, P4 p4) { return fn(p1, p2, p3, p4); } + + LambdaGate4(std::function fn) : fn(fn) {} +}; +#endif + template class Gate4 : Moveable< Gate4 > { Gate4Action *action; @@ -613,6 +742,9 @@ public: explicit Gate4(Gate4Action *newaction) { action = newaction; } Gate4() { action = NULL; } Gate4(_CNULL) { action = NULL; } +#ifdef HAS_LAMBDA + Gate4& operator=(std::function l) { Clear(); action = new LambdaGate4(l); return *this; } +#endif ~Gate4(); static Gate4 Empty() { return CNULL; } diff --git a/uppsrc/Core/src.tpp/Callbacks$en-us.tpp b/uppsrc/Core/src.tpp/Callbacks$en-us.tpp index 0f56e503b..491e84b8e 100644 --- a/uppsrc/Core/src.tpp/Callbacks$en-us.tpp +++ b/uppsrc/Core/src.tpp/Callbacks$en-us.tpp @@ -15,6 +15,8 @@ topic "Callbacks"; pointers. Each Callback represents some kind of action (usually calling a certain function or a certain object method) that can be invoked at any time.&] +[s9; If you are happy enough to be able to use C`+`+11, you can also +assign C`+`+ lambda to Callback.&] [s9; There are several basic callback types, depending on number of parameters passed and return value. In order to keep description of callbacks short, all these types are described in a single @@ -84,6 +86,13 @@ Callback takes over its ownership.&] [s0;:Callback1`:`:Callback1`(`):%- [%%*/@(128.0.255) CallbackType]()&] [s2; Creates an empty callback.&] [s3; &] +[s4;%- &] +[s5;:Callback1`:`:operator`=`(function``):%- [_^Callback1^ Callback1][@(0.0.255) `& +]_[* operator`=](std`::function<[@(0.0.255) void]_([%%*/@(128.0.255) arguments])>_[*@3 lam +bda])&] +[s6;%- Only in C`+`+ 11&] +[s2; Assigns C`+`+11 lambda to callback.&] +[s3; &] [s4; &] [s0;:Callback1`:`:Callback1`(const Callback1`&`):%- [%%*/@(128.0.255) CallbackType](con st_[%%*/@(128.0.255) CallbackType]`&_[*@3 c])&]