瀏覽代碼

Add promise package.

julianyang 2 年之前
父節點
當前提交
68e20b7cf6
共有 36 個文件被更改,包括 2947 次插入17 次删除
  1. 27 0
      examples/PromiseDemo/AServer/AServant.tars
  2. 252 0
      examples/PromiseDemo/AServer/AServantImp.cpp
  3. 62 0
      examples/PromiseDemo/AServer/AServantImp.h
  4. 57 0
      examples/PromiseDemo/AServer/AServer.cpp
  5. 52 0
      examples/PromiseDemo/AServer/AServer.h
  6. 25 0
      examples/PromiseDemo/AServer/BServant.tars
  7. 25 0
      examples/PromiseDemo/AServer/CServant.tars
  8. 12 0
      examples/PromiseDemo/AServer/makefile
  9. 25 0
      examples/PromiseDemo/BServer/BServant.tars
  10. 45 0
      examples/PromiseDemo/BServer/BServantImp.cpp
  11. 40 0
      examples/PromiseDemo/BServer/BServantImp.h
  12. 57 0
      examples/PromiseDemo/BServer/BServer.cpp
  13. 52 0
      examples/PromiseDemo/BServer/BServer.h
  14. 11 0
      examples/PromiseDemo/BServer/makefile
  15. 25 0
      examples/PromiseDemo/CServer/CServant.tars
  16. 45 0
      examples/PromiseDemo/CServer/CServantImp.cpp
  17. 40 0
      examples/PromiseDemo/CServer/CServantImp.h
  18. 57 0
      examples/PromiseDemo/CServer/CServer.cpp
  19. 53 0
      examples/PromiseDemo/CServer/CServer.h
  20. 11 0
      examples/PromiseDemo/CServer/makefile
  21. 138 0
      examples/PromiseDemo/Client/main.cpp
  22. 13 0
      examples/PromiseDemo/Client/makefile
  23. 6 0
      examples/PromiseDemo/README.md
  24. 1 0
      servant/CMakeLists.txt
  25. 50 0
      servant/promise/bind.h
  26. 316 0
      servant/promise/bind_internal.h
  27. 119 0
      servant/promise/callback.h
  28. 109 0
      servant/promise/exception.h
  29. 53 0
      servant/promise/function.h
  30. 806 0
      servant/promise/promise.h
  31. 29 0
      servant/promise/template_helper.h
  32. 128 0
      servant/promise/type_list.h
  33. 195 0
      servant/promise/when_all.h
  34. 3 9
      tools/tars2cpp/tars2cpp.cpp
  35. 6 6
      tools/tars2cpp/tars2cpp.h
  36. 2 2
      util/include/util/tc_thread_rwlock.h

+ 27 - 0
examples/PromiseDemo/AServer/AServant.tars

@@ -0,0 +1,27 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+module Test
+{
+
+interface AServant
+{
+    int queryResultSerial(string sIn, out string sOut);
+    
+    int queryResultParallel(string sIn, out string sOut);
+};
+
+}; 

+ 252 - 0
examples/PromiseDemo/AServer/AServantImp.cpp

@@ -0,0 +1,252 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "AServantImp.h"
+#include "AServer.h"
+#include "servant/Application.h"
+#include "servant/Communicator.h"
+
+using namespace std;
+using namespace tars;
+
+//////////////////////////////////////////////////////
+class BServantCallback : public BServantPrxCallback
+{
+
+public:
+    BServantCallback(TarsCurrentPtr &current)
+    : _current(current)
+    {}
+
+    BServantCallback(TarsCurrentPtr &current, const tars::Promise<std::string> &promise)
+    : _current(current)
+    , _promise(promise)
+    {}
+
+    void callback_queryResult(tars::Int32 ret, const std::string &sOut)
+    {
+        if(ret == 0)
+        {
+            _promise.setValue(sOut);
+        }
+        else
+        {
+            handExp("callback_queryResult", ret);
+        }
+    }
+    void callback_queryResult_exception(tars::Int32 ret)
+    {
+        handExp("callback_queryResult_exception", ret);
+    }
+
+private:
+    void handExp(const std::string &sFuncName, tars::Int32 ret)
+    {
+        string s("sFuncName:");
+        s += sFuncName;
+        s += "|ret:";
+        s += TC_Common::tostr(ret);
+
+        _promise.setException(tars::copyException(s, -1));
+
+        TLOGDEBUG("ServerPrxCallback handExp:" << s << endl);
+    }
+
+private:
+
+    TarsCurrentPtr                    _current;
+    tars::Promise<std::string>    _promise;
+};
+//////////////////////////////////////////////////////
+class CServantCallback : public CServantPrxCallback
+{
+
+public:
+    CServantCallback(TarsCurrentPtr &current)
+    : _current(current)
+    {}
+
+    CServantCallback(TarsCurrentPtr &current, const tars::Promise<std::string> &promise)
+    : _current(current)
+    , _promise(promise)
+    {}
+
+    void callback_queryResult(tars::Int32 ret, const std::string &sOut)
+    {
+        if(ret == 0)
+        {
+            _promise.setValue(sOut);
+        }
+        else
+        {
+            handExp("callback_queryResult", ret);
+        }
+    }
+    void callback_queryResult_exception(tars::Int32 ret)
+    {
+        handExp("callback_queryResult_exception", ret);
+    }
+
+private:
+    void handExp(const std::string &sFuncName, tars::Int32 ret)
+    {
+        string s("sFuncName:");
+        s += sFuncName;
+        s += "|ret:";
+        s += TC_Common::tostr(ret);
+
+        _promise.setException(tars::copyException(s, -1));
+
+        TLOGDEBUG("ServerPrxCallback handExp:" << s << endl);
+    }
+
+private:
+
+    TarsCurrentPtr                    _current;
+    tars::Promise<std::string>    _promise;
+};
+//////////////////////////////////////////////////////
+tars::Future<std::string> sendBReq(BServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current)
+{
+    tars::Promise<std::string> promise;
+
+    Test::BServantPrxCallbackPtr cb = new BServantCallback(current, promise);
+
+    prx->async_queryResult(cb, sIn);
+
+    return promise.getFuture();
+}
+//////////////////////////////////////////////////////
+tars::Future<std::string> sendCReq(CServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current)
+{
+    tars::Promise<std::string> promise;
+
+    Test::CServantPrxCallbackPtr cb = new CServantCallback(current, promise);
+
+    prx->async_queryResult(cb, sIn);
+
+    return promise.getFuture();
+}
+//////////////////////////////////////////////////////
+tars::Future<std::string> handleBRspAndSendCReq(CServantPrx prx, TarsCurrentPtr current, const tars::Future<std::string>& future)
+{
+    std::string sResult("");
+    std::string sException("");
+    try 
+    {
+        sResult = future.get();
+
+        return sendCReq(prx, sResult, current);
+    } 
+    catch (exception& e) 
+    {
+        TLOGDEBUG("Exception:" << e.what() << endl);
+        sException = e.what();
+    }
+
+    tars::Promise<std::string> promise;
+    promise.setValue(sException);
+
+    return promise.getFuture();
+}
+//////////////////////////////////////////////////////
+int handleCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::string>& future)
+{
+    int ret = 0;
+    std::string sResult("");
+    try 
+    {
+        sResult = future.get();
+    } 
+    catch (exception& e) 
+    {
+        ret = -1;
+        sResult = e.what();
+
+        TLOGDEBUG("Exception:" << e.what() << endl);
+    }
+
+    AServant::async_response_queryResultSerial(current, ret, sResult);
+
+    return 0;
+}
+//////////////////////////////////////////////////////
+int handleBCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::tuple<tars::Future<std::string>, tars::Future<std::string> > >& allFuture)
+{
+    int ret = 0;
+    std::string sResult("");
+    try 
+    {
+        const std::tuple<tars::Future<std::string>, tars::Future<std::string> >& tupleFuture = allFuture.get();
+
+        std::string sResult1 = std::get<0>(tupleFuture).get();
+        std::string sResult2 = std::get<1>(tupleFuture).get();
+
+        sResult = sResult1;
+        sResult += "|";
+        sResult += sResult2;
+    } 
+    catch (exception& e) 
+    {
+        ret = -1;
+        sResult = e.what();
+
+        TLOGDEBUG("Exception:" << e.what() << endl);
+    }
+
+    AServant::async_response_queryResultParallel(current, ret, sResult);
+
+    return 0;
+}
+//////////////////////////////////////////////////////
+void AServantImp::initialize()
+{
+    //initialize servant here:
+    //...
+    _pPrxB = Application::getCommunicator()->stringToProxy<BServantPrx>("Test.BServer.BServantObj");
+    _pPrxC = Application::getCommunicator()->stringToProxy<CServantPrx>("Test.CServer.CServantObj");
+}
+//////////////////////////////////////////////////////
+void AServantImp::destroy()
+{
+}
+//////////////////////////////////////////////////////
+tars::Int32 AServantImp::queryResultSerial(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
+{
+    current->setResponse(false);
+
+    tars::Future<std::string> f = sendBReq(_pPrxB, sIn, current);
+
+    f.then(tars::Bind(&handleBRspAndSendCReq, _pPrxC, current)).then(tars::Bind(&handleCRspAndReturnClient, current));
+
+    return 0;
+}
+//////////////////////////////////////////////////////
+tars::Int32 AServantImp::queryResultParallel(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
+{
+    current->setResponse(false);
+
+    tars::Future<std::string> f1 = sendBReq(_pPrxB, sIn, current);
+
+    tars::Future<std::string> f2 = sendCReq(_pPrxC, sIn, current);
+
+    tars::Future<std::tuple<tars::Future<std::string>, tars::Future<std::string> > > f_all = tars::WhenAll(f1, f2);
+
+    f_all.then(tars::Bind(&handleBCRspAndReturnClient, current));
+
+    return 0;
+}
+

+ 62 - 0
examples/PromiseDemo/AServer/AServantImp.h

@@ -0,0 +1,62 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServantImp_H_
+#define _BServantImp_H_
+
+#include <tuple>
+#include "servant/Application.h"
+#include "AServant.h"
+#include "BServant.h"
+#include "CServant.h"
+#include "promise/promise.h"
+#include "promise/when_all.h"
+
+using namespace Test;
+
+///////////////////////////////////
+tars::Future<std::string> sendBReq(BServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current);
+
+tars::Future<std::string> handleBRspAndSendCReq(CServantPrx prx, TarsCurrentPtr current, const tars::Future<std::string>& future);
+
+tars::Future<std::string> sendCReq(CServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current);
+
+int handleCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::string>& future);
+
+///////////////////////////////////
+int handleBCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::tuple<tars::Future<std::string>, tars::Future<std::string> > >& allFuture);
+
+///////////////////////////////////
+class AServantImp : public Test::AServant
+{
+public:
+
+    virtual ~AServantImp() {}
+
+    virtual void initialize();
+
+    virtual void destroy();
+
+    tars::Int32 queryResultSerial(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current);
+
+    tars::Int32 queryResultParallel(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current);
+
+private:
+    BServantPrx _pPrxB;
+    CServantPrx _pPrxC;
+};
+/////////////////////////////////////////////////////
+#endif

+ 57 - 0
examples/PromiseDemo/AServer/AServer.cpp

@@ -0,0 +1,57 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "AServer.h"
+#include "AServantImp.h"
+
+using namespace std;
+
+AServer g_app;
+
+/////////////////////////////////////////////////////////////////
+void AServer::initialize()
+{
+    //initialize application here:
+    //... 
+
+    addServant<AServantImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".AServantObj");
+}
+/////////////////////////////////////////////////////////////////
+void AServer::destroyApp()
+{
+    //destroy application here:
+    //...
+}
+
+/////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    try
+    {
+        g_app.main(argc, argv);
+        g_app.waitForShutdown();
+    }
+    catch (std::exception& e)
+    {
+        cerr << "std::exception:" << e.what() << std::endl;
+    }
+    catch (...)
+    {
+        cerr << "unknown exception." << std::endl;
+    }
+    return -1;
+}
+/////////////////////////////////////////////////////////////////

+ 52 - 0
examples/PromiseDemo/AServer/AServer.h

@@ -0,0 +1,52 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServer_H_
+#define _BServer_H_
+
+#include <iostream>
+#include "servant/Application.h"
+
+using namespace tars;
+
+/**
+ *
+ **/
+class AServer : public Application
+{
+public:
+    /**
+     *
+     **/
+    virtual ~AServer() {};
+
+    /**
+     *
+     **/
+    virtual void initialize();
+
+    /**
+     *
+     **/
+    virtual void destroyApp();
+protected:
+    bool cmdprofile(const string& command, const string& params, string& result);
+};
+
+extern AServer g_app;
+
+////////////////////////////////////////////
+#endif

+ 25 - 0
examples/PromiseDemo/AServer/BServant.tars

@@ -0,0 +1,25 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+module Test
+{
+
+interface BServant
+{
+    int queryResult(string sIn, out string sOut);
+};
+
+}; 

+ 25 - 0
examples/PromiseDemo/AServer/CServant.tars

@@ -0,0 +1,25 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+module Test
+{
+
+interface CServant
+{
+    int queryResult(string sIn, out string sOut);
+};
+
+}; 

+ 12 - 0
examples/PromiseDemo/AServer/makefile

@@ -0,0 +1,12 @@
+
+#-----------------------------------------------------------------------
+APP       := Test
+TARGET    := AServer
+CONFIG    := 
+STRIP_FLAG:= N
+
+INCLUDE   +=
+
+#-----------------------------------------------------------------------
+include /usr/local/tars/cpp/makefile/makefile.tars
+#-----------------------------------------------------------------------

+ 25 - 0
examples/PromiseDemo/BServer/BServant.tars

@@ -0,0 +1,25 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+module Test
+{
+
+interface BServant
+{
+    int queryResult(string sIn, out string sOut);
+};
+
+}; 

+ 45 - 0
examples/PromiseDemo/BServer/BServantImp.cpp

@@ -0,0 +1,45 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "BServantImp.h"
+#include "BServer.h"
+#include "servant/Application.h"
+#include "servant/Communicator.h"
+
+using namespace std;
+using namespace tars;
+
+//////////////////////////////////////////////////////
+void BServantImp::initialize()
+{
+    //initialize servant here:
+    //...
+}
+//////////////////////////////////////////////////////
+void BServantImp::destroy()
+{
+}
+//////////////////////////////////////////////////////
+tars::Int32 BServantImp::queryResult(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
+{
+    sOut = "[sResult:";
+    sOut += sIn;
+    sOut += "]";
+
+    return 0;
+}
+
+

+ 40 - 0
examples/PromiseDemo/BServer/BServantImp.h

@@ -0,0 +1,40 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServantImp_H_
+#define _BServantImp_H_
+
+#include "servant/Application.h"
+#include "BServant.h"
+#include "promise/promise.h"
+
+using namespace Test;
+
+class BServantImp : public Test::BServant
+{
+public:
+
+    virtual ~BServantImp() {}
+
+    virtual void initialize();
+
+    virtual void destroy();
+
+    tars::Int32 queryResult(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current);
+
+};
+/////////////////////////////////////////////////////
+#endif

+ 57 - 0
examples/PromiseDemo/BServer/BServer.cpp

@@ -0,0 +1,57 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "BServer.h"
+#include "BServantImp.h"
+
+using namespace std;
+
+BServer g_app;
+
+/////////////////////////////////////////////////////////////////
+void BServer::initialize()
+{
+    //initialize application here:
+    //... 
+
+    addServant<BServantImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".BServantObj");
+}
+/////////////////////////////////////////////////////////////////
+void BServer::destroyApp()
+{
+    //destroy application here:
+    //...
+}
+
+/////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    try
+    {
+        g_app.main(argc, argv);
+        g_app.waitForShutdown();
+    }
+    catch (std::exception& e)
+    {
+        cerr << "std::exception:" << e.what() << std::endl;
+    }
+    catch (...)
+    {
+        cerr << "unknown exception." << std::endl;
+    }
+    return -1;
+}
+/////////////////////////////////////////////////////////////////

+ 52 - 0
examples/PromiseDemo/BServer/BServer.h

@@ -0,0 +1,52 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServer_H_
+#define _BServer_H_
+
+#include <iostream>
+#include "servant/Application.h"
+
+using namespace tars;
+
+/**
+ *
+ **/
+class BServer : public Application
+{
+public:
+    /**
+     *
+     **/
+    virtual ~BServer() {};
+
+    /**
+     *
+     **/
+    virtual void initialize();
+
+    /**
+     *
+     **/
+    virtual void destroyApp();
+protected:
+    bool cmdprofile(const string& command, const string& params, string& result);
+};
+
+extern BServer g_app;
+
+////////////////////////////////////////////
+#endif

+ 11 - 0
examples/PromiseDemo/BServer/makefile

@@ -0,0 +1,11 @@
+#-----------------------------------------------------------------------
+
+APP       := Test
+TARGET    := BServer
+CONFIG    := 
+STRIP_FLAG:= N
+INCLUDE   +=
+
+#-----------------------------------------------------------------------
+include /usr/local/tars/cpp/makefile/makefile.tars
+#-----------------------------------------------------------------------

+ 25 - 0
examples/PromiseDemo/CServer/CServant.tars

@@ -0,0 +1,25 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+module Test
+{
+
+interface CServant
+{
+    int queryResult(string sIn, out string sOut);
+};
+
+}; 

+ 45 - 0
examples/PromiseDemo/CServer/CServantImp.cpp

@@ -0,0 +1,45 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "CServantImp.h"
+#include "CServer.h"
+#include "servant/Application.h"
+#include "servant/Communicator.h"
+
+using namespace std;
+using namespace tars;
+
+//////////////////////////////////////////////////////
+void CServantImp::initialize()
+{
+    //initialize servant here:
+    //...
+}
+//////////////////////////////////////////////////////
+void CServantImp::destroy()
+{
+}
+//////////////////////////////////////////////////////
+tars::Int32 CServantImp::queryResult(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
+{
+    sOut = "[sResult:";
+    sOut += sIn;
+    sOut += "]";
+
+    return 0;
+}
+
+

+ 40 - 0
examples/PromiseDemo/CServer/CServantImp.h

@@ -0,0 +1,40 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServantImp_H_
+#define _BServantImp_H_
+
+#include "servant/Application.h"
+#include "CServant.h"
+#include "promise/promise.h"
+
+using namespace Test;
+
+class CServantImp : public Test::CServant
+{
+public:
+
+    virtual ~CServantImp() {}
+
+    virtual void initialize();
+
+    virtual void destroy();
+
+    tars::Int32 queryResult(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current);
+
+};
+/////////////////////////////////////////////////////
+#endif

+ 57 - 0
examples/PromiseDemo/CServer/CServer.cpp

@@ -0,0 +1,57 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "CServer.h"
+#include "CServantImp.h"
+
+using namespace std;
+
+CServer g_app;
+
+/////////////////////////////////////////////////////////////////
+void CServer::initialize()
+{
+    //initialize application here:
+    //... 
+
+    addServant<CServantImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".CServantObj");
+}
+/////////////////////////////////////////////////////////////////
+void CServer::destroyApp()
+{
+    //destroy application here:
+    //...
+}
+
+/////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    try
+    {
+        g_app.main(argc, argv);
+        g_app.waitForShutdown();
+    }
+    catch (std::exception& e)
+    {
+        cerr << "std::exception:" << e.what() << std::endl;
+    }
+    catch (...)
+    {
+        cerr << "unknown exception." << std::endl;
+    }
+    return -1;
+}
+/////////////////////////////////////////////////////////////////

+ 53 - 0
examples/PromiseDemo/CServer/CServer.h

@@ -0,0 +1,53 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _BServer_H_
+#define _BServer_H_
+
+#include <iostream>
+#include "servant/Application.h"
+
+using namespace tars;
+
+/**
+ *  *
+ *   **/
+class CServer : public Application
+{
+public:
+    /**
+     *
+     **/
+    virtual ~CServer() {};
+
+    /**
+     *
+     **/
+    virtual void initialize();
+
+    /**
+     *
+     **/
+    virtual void destroyApp();
+protected:
+    bool cmdprofile(const string& command, const string& params, string& result);
+};
+
+extern CServer g_app;
+
+////////////////////////////////////////////
+#endif
+

+ 11 - 0
examples/PromiseDemo/CServer/makefile

@@ -0,0 +1,11 @@
+#-----------------------------------------------------------------------
+APP       := Test
+TARGET    := CServer
+CONFIG    := 
+STRIP_FLAG:= N 
+
+INCLUDE   +=
+
+#-----------------------------------------------------------------------
+include /usr/local/tars/cpp/makefile/makefile.tars
+#-----------------------------------------------------------------------

+ 138 - 0
examples/PromiseDemo/Client/main.cpp

@@ -0,0 +1,138 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "AServant.h"
+#include "servant/Communicator.h"
+#include "util/tc_thread_pool.h"
+#include <iostream>
+
+using namespace std;
+using namespace Test;
+using namespace tars;
+
+class Test1
+{
+public:
+    Test1(const string &sStr);
+
+    ~Test1();
+
+    void  queryResult(int iFlag, int iExecuteNum);
+
+private:
+    Communicator    _comm;
+    AServantPrx        prx;
+};
+
+Test1::Test1(const string &sStr)
+{
+    _comm.setProperty("locator", "tars.tarsregistry.QueryObj@tcp -h 172.22.32.115 -t 60000 -p 17890");
+    _comm.stringToProxy(sStr, prx);
+}
+
+Test1::~Test1()
+{
+    
+}
+
+void Test1::queryResult(int iFlag, int iExecuteNum)
+{
+    string sIn(10,'a');
+    string sOut("");
+
+    tars::Int32 count = 0;
+    unsigned long sum = 0;
+
+    time_t _iTime=TC_TimeProvider::getInstance()->getNowMs();
+
+    for(int i=0; i<iExecuteNum; i++) 
+    {
+        sOut = "";
+        try
+        {
+            int ret = -1;
+            if(iFlag == 0)
+            {
+                ret = prx->queryResultSerial(sIn, sOut);
+            }
+            else
+            {
+                ret = prx->queryResultParallel(sIn, sOut);
+            }
+
+            if(ret == 0)
+            {
+                ++sum;
+                ++count;
+                if(count == iExecuteNum)
+                {
+                    cout << "pthread id: " << pthread_self() << " | " << TC_TimeProvider::getInstance()->getNowMs() - _iTime << endl;
+                    _iTime=TC_TimeProvider::getInstance()->getNowMs();
+                    count = 0;
+                }
+            }
+        }
+        catch(TC_Exception &e)
+        {
+            cout << "pthread id: " << pthread_self() << "id: " << i << "exception: " << e.what() << endl;
+        }
+        catch(...)
+        {
+            cout << "pthread id: " << pthread_self() << "id: " << i << "unknown exception." << endl;
+        }
+    }
+    cout << "succ:" << sum << endl;
+    cout << "sOut:" << sOut << endl;
+}
+
+int main(int argc,char ** argv)
+{
+    if(argc != 5)
+    {
+        cout << "usage: " << argv[0] << " sObj ThreadNum CallTimes  CallMode" << endl;
+        return -1;
+    }
+
+    string s = string(argv[1]);
+
+    Test1 test1(s);
+    try
+    {
+        tars::Int32 threads = TC_Common::strto<tars::Int32>(string(argv[2]));
+        TC_ThreadPool tp;
+        tp.init(threads);
+        tp.start();
+        tars::Int32 times = TC_Common::strto<tars::Int32>(string(argv[3]));
+        tars::Int32 callMode = TC_Common::strto<tars::Int32>(string(argv[4]));
+        
+        for(int i = 0; i<threads; i++) 
+        {
+            auto fw = std::bind(&Test1::queryResult, &test1, callMode, times);
+            tp.exec(fw);
+            cout << "********************" <<endl;
+        }
+        tp.waitForAllDone(); 
+    }catch(exception &e)
+    {
+        cout<<e.what()<<endl;
+    }
+    catch(...)
+    {
+        
+    }
+    
+    return 0;
+}

+ 13 - 0
examples/PromiseDemo/Client/makefile

@@ -0,0 +1,13 @@
+
+#-----------------------------------------------------------------------
+APP       := Test
+TARGET    := myClientPromise
+CONFIG    := 
+STRIP_FLAG:= N
+
+INCLUDE   +=
+
+#-----------------------------------------------------------------------
+include /home/tarsproto/Test/AServer/AServer.mk
+include /usr/local/tars/cpp/makefile/makefile.tars
+#-----------------------------------------------------------------------

+ 6 - 0
examples/PromiseDemo/README.md

@@ -0,0 +1,6 @@
+该工程是Tars promise编程示例的代码
+
+
+目录名称 |功能
+-----------------|----------------
+AServer   |   promise编程的示例程序,用promsie方式去并行和串行访问BServer和CServer

+ 1 - 0
servant/CMakeLists.txt

@@ -67,6 +67,7 @@ add_subdirectory(tup)
 add_subdirectory(libservant)
 
 install(DIRECTORY servant DESTINATION include)
+install(DIRECTORY promise DESTINATION include)
 install(DIRECTORY tup DESTINATION include)
 install(DIRECTORY jmem DESTINATION include)
 install(DIRECTORY script DESTINATION .

+ 50 - 0
servant/promise/bind.h

@@ -0,0 +1,50 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_BIND_H_
+#define _TARS_BIND_H_
+
+#include "promise/bind_internal.h"
+#include "promise/callback.h"
+
+namespace tars {
+
+template <typename Functor, typename... Args>
+struct MakeUnboundRunTypeImpl {
+    using Type = typename bind::BindState<
+        typename bind::FunctorTraits<Functor>::RunnableType,
+                 typename bind::FunctorTraits<Functor>::RunType,
+                 Args...>::UnboundRunType;
+
+};
+
+template <typename Functor, typename... Args>
+using MakeUnboundRunType = typename MakeUnboundRunTypeImpl<Functor, Args...>::Type;
+
+template <typename Functor, typename... Args>
+Callback<MakeUnboundRunType<Functor, Args...> > Bind(Functor f, Args&&... args)
+{
+    using RunnableType = typename bind::FunctorTraits<Functor>::RunnableType;
+    using RunType = typename bind::FunctorTraits<Functor>::RunType;
+    using BindState = bind::BindState<RunnableType, RunType, Args...>;
+
+    return Callback<typename BindState::UnboundRunType>(
+            new BindState(bind::MakeRunnable(f), std::forward<Args>(args)...));
+}
+
+} // end namespace tars
+
+#endif

+ 316 - 0
servant/promise/bind_internal.h

@@ -0,0 +1,316 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_BIND_INTERNAL_H_
+#define _TARS_BIND_INTERNAL_H_
+
+#include <memory>
+#include <tuple>
+#include <vector>
+#include "promise/function.h"
+
+namespace tars {
+
+namespace bind {
+
+template <size_t...>
+struct IndexSequence {};
+
+template <size_t... Ns>
+struct MakeIndexSequenceImpl;
+
+template <size_t... Ns>
+struct MakeIndexSequenceImpl<0, Ns...> {
+    using Type = IndexSequence<Ns...>;
+};
+
+template <size_t N, size_t... Ns>
+struct MakeIndexSequenceImpl<N, Ns...> 
+                : MakeIndexSequenceImpl<N-1, N-1, Ns...> {};
+
+template <size_t N>
+using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type;
+
+// Used to implement MakeArgsStorage.
+template <bool IsRefCall, typename... BoundArgs>
+struct MakeArgsStorageImpl {
+    using Type = std::tuple<BoundArgs...>;
+};
+
+template <typename Obj, typename... BoundArgs>
+struct MakeArgsStorageImpl<true, Obj*, BoundArgs...> {
+    using Type = std::tuple<std::shared_ptr<Obj>, BoundArgs...>;
+};
+
+template <bool IsRefCall, typename... BoundArgs>
+using MakeArgsStorage = typename MakeArgsStorageImpl<IsRefCall, 
+      typename std::decay<BoundArgs>::type...>::Type;
+
+
+class BindStateBase : public std::enable_shared_from_this<BindStateBase> {
+public:
+    virtual ~BindStateBase() {};
+
+protected:
+    BindStateBase() {}
+};
+
+template <typename Functor>
+class RunnableAdapter;
+
+template <typename R, typename... Args>
+class RunnableAdapter<R(*)(Args...)> {
+public:
+    typedef R RunType(Args...); 
+
+    using IsMethod = std::false_type;
+
+    explicit RunnableAdapter(R(*f)(Args...))
+        : m_function(f)
+    {
+    }
+
+    template <typename... RunArgs>
+    R run(RunArgs&&... args) 
+    {
+        return m_function(std::forward<RunArgs>(args)...);
+    }
+
+private:
+    R (*m_function)(Args...);
+};
+
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...)> {
+public:
+    typedef R RunType(T*, Args...);
+
+    using IsMethod = std::true_type;
+
+    explicit RunnableAdapter(R(T::*f)(Args...))
+        : m_function(f)
+    {
+    }
+
+    template <typename... RunArgs>
+    R run(T* obj, RunArgs&&... args) 
+    {
+        return (obj->*m_function)(std::forward<RunArgs>(args)...);
+    }
+
+private:
+    R (T::*m_function)(Args...);
+};
+
+template <typename R, typename T, typename... Args>
+class RunnableAdapter<R(T::*)(Args...) const> {
+public:
+    typedef R RunType(const T*, Args...);
+
+    using IsMethod = std::true_type;
+
+    explicit RunnableAdapter(R(T::*f)(Args...) const)
+        : m_function(f)
+    {
+    }
+
+    template <typename... RunArgs>
+    R run(const T* obj, RunArgs&&... args) 
+    {
+        return (obj->*m_function)(std::forward<RunArgs>(args)...);
+    }
+
+private:
+    R (T::*m_function)(Args...) const;
+};
+
+template <typename T>
+struct FunctorTraits {
+    using RunnableType = RunnableAdapter<T>;
+    using RunType = typename RunnableType::RunType;
+};
+
+template <typename T>
+typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
+    return RunnableAdapter<T>(t);
+}
+
+template <bool IsRefCall, typename R, typename Runnable>
+struct InvokeHelper;
+
+template <typename R, typename Runnable>
+struct InvokeHelper<false, R, Runnable> {
+    template <typename... RunArgs>
+    static R makeItSo(Runnable r, RunArgs&&... args) 
+    {
+        return r.run(std::forward<RunArgs>(args)...);
+    }
+};
+
+template <typename Runnable>
+struct InvokeHelper<false, void, Runnable> {
+    template <typename... RunArgs>
+    static void makeItSo(Runnable r, RunArgs&&... args) 
+    {
+        r.run(std::forward<RunArgs>(args)...);
+    }
+};
+
+template <typename R, typename Runnable>
+struct InvokeHelper<true, R, Runnable> {
+    template <typename RefPtr, typename... RunArgs>
+    static R makeItSo(Runnable r, RefPtr p, RunArgs&&... args) 
+    {
+        return r.run(p.get(), std::forward<RunArgs>(args)...);
+    }
+};
+
+template <typename Runnable>
+struct InvokeHelper<true, void, Runnable> {
+    template <typename RefPtr, typename... RunArgs>
+    static void makeItSo(Runnable r, RefPtr p, RunArgs&&... args) 
+    {
+        r.run(p.get(), std::forward<RunArgs>(args)...);
+    }
+};
+
+template <typename T>
+const T& Unwrap(const T& o) {
+    return o;
+}
+
+template <typename T> 
+struct IsMoveOnlyType : public std::false_type {};
+
+template <typename T, typename D>
+struct IsMoveOnlyType<std::unique_ptr<T, D> > : public std::true_type {};
+
+template <typename T, typename A>
+struct IsMoveOnlyType<std::vector<T, A> > : public IsMoveOnlyType<T> {};
+
+template <typename T>
+struct ParamForwardTypeNonMoveOnly {
+    using ForwardType = const T&;
+};
+
+template <typename T, size_t N>
+struct ParamForwardTypeNonMoveOnly<T[N]> {
+    using ForwardType = const T*;
+};
+
+template <typename T>
+struct ParamForwardTypeNonMoveOnly<T[]> {
+    using ForwardType = const T*;
+};
+
+template <typename T>
+struct ParamForwardTypeMoveOnly {
+    using ForwardType = T;
+};
+
+template <typename T>
+enable_if_t<!IsMoveOnlyType<T>::value, T>& ParamForward(T& t)
+{
+    return t;
+}
+
+template <typename T>
+enable_if_t<IsMoveOnlyType<T>::value, T>& ParamForward(T& t)
+{
+    return std::move(t);
+}
+
+template <typename T>
+struct ParamTraits : public std::conditional<IsMoveOnlyType<T>::value, 
+                ParamForwardTypeMoveOnly<T>, 
+                ParamForwardTypeNonMoveOnly<T> >::type {};
+
+template <typename BoundIndices, typename StorageType,
+         typename InvokeHelperType, typename UnboundForwardRunType>
+struct Invoker;
+
+template <size_t... BoundIndices,
+         typename StorageType,
+         typename InvokeHelperType,
+         typename R,
+         typename... UnboundForwardArgs>
+struct Invoker<IndexSequence<BoundIndices...>, StorageType,
+               InvokeHelperType, R(UnboundForwardArgs...)> {
+    static R run(BindStateBase* base, UnboundForwardArgs... unbound_args) 
+    {
+        StorageType* storage = static_cast<StorageType*>(base);
+        return InvokeHelperType::makeItSo(storage->m_runnable,
+                Unwrap(std::get<BoundIndices>(storage->m_boundArgs))...,
+                ParamForward(unbound_args)...);
+    }
+};
+
+template <bool IsMethod, typename... Args>
+struct IsRefMethod : public std::false_type {};
+
+template <typename T, typename... Args>
+struct IsRefMethod<true, std::shared_ptr<T>, Args...> 
+                : public std::true_type {};
+
+template <typename Runnable, typename RunType, typename... BoundArgs>
+struct BindState;
+
+template <typename Runnable, 
+         typename R, 
+         typename... Args, 
+         typename... BoundArgs>
+struct BindState<Runnable, R(Args...), BoundArgs...> final 
+                : public BindStateBase {
+private:
+    using StorageType = BindState<Runnable, R(Args...), BoundArgs...>;
+    using RunnableType = Runnable;
+
+    using IsRefCall = IsRefMethod<Runnable::IsMethod::value, 
+          typename std::decay<BoundArgs>::type...>;
+
+    using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
+    using UnboundForwardArgs = tl::DropTypeListItem<sizeof...(BoundArgs),
+          tl::TypeList<typename ParamTraits<Args>::ForwardType...> >;
+
+    using UnboundForwardRunType = f::MakeFunctionType<R, UnboundForwardArgs>;
+    using InvokeHelperType = InvokeHelper<IsRefCall::value, R, Runnable>;
+    using UnboundArgs = tl::DropTypeListItem<sizeof...(BoundArgs), 
+          tl::TypeList<Args...> >;
+
+public:
+    using InvokerType = Invoker<BoundIndices, 
+          StorageType, 
+          InvokeHelperType, 
+          UnboundForwardRunType>;
+
+    using UnboundRunType = f::MakeFunctionType<R, UnboundArgs>;
+
+    template <typename... ForwardArgs>
+    BindState(const Runnable& runnable, ForwardArgs&&... boundArgs)
+        : m_runnable(runnable)
+        , m_boundArgs(std::forward<ForwardArgs>(boundArgs)...)
+    {
+    }
+
+    RunnableType m_runnable;
+    MakeArgsStorage<IsRefCall::value, BoundArgs...> m_boundArgs;
+};
+
+} // end namespace bind
+
+} // end namespace tars
+
+#endif

+ 119 - 0
servant/promise/callback.h

@@ -0,0 +1,119 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_CALL_BACK_H_
+#define _TARS_CALL_BACK_H_
+
+#include <memory>
+#include "promise/bind_internal.h"
+
+namespace tars {
+
+namespace cb {
+
+// class CallbackBase
+class CallbackBase {
+public:
+    bool isNull() const { return m_bindState.get() == nullptr; }
+    void reset() { m_bindState = nullptr, m_function = nullptr; }
+
+    virtual ~CallbackBase() {}
+
+    explicit operator bool () const
+    {
+        return !isNull();
+    }
+
+protected:
+
+    using InvokeFunctionStorage = void(*)();
+	
+    bool equals(const CallbackBase& other) const
+    {
+        return m_bindState.get() == other.m_bindState.get()
+            && m_function == other.m_function;
+    }
+
+    explicit CallbackBase(bind::BindStateBase* bindState)
+        : m_bindState(bindState)
+        , m_function(nullptr)
+    {
+    }
+
+    CallbackBase(const CallbackBase& o)
+        : m_bindState(o.m_bindState)
+        , m_function(o.m_function)
+    {
+    }
+
+    CallbackBase(CallbackBase&& o)
+        : m_bindState(std::move(o.m_bindState))
+        , m_function(o.m_function)
+    {
+        o.m_function = nullptr;
+    }
+
+
+    // bind state with specific parameter.
+    std::shared_ptr<bind::BindStateBase> m_bindState;
+
+    // pointer to function address.
+    InvokeFunctionStorage m_function;
+};
+
+} // end namespace cb
+
+template <typename T>
+class Callback;
+
+template <typename R, typename... Args>
+class Callback<R(Args...)> : public cb::CallbackBase {
+    typedef R(*PolymorphicInvoke)(bind::BindStateBase*, typename bind::ParamTraits<Args>::ForwardType...);
+public:
+    typedef R RunType(Args...);
+    
+    Callback() 
+        : cb::CallbackBase(nullptr) 
+    { 
+    }
+
+	template <typename Runnable, typename BindRunType, typename... BoundArgsType>
+    Callback(bind::BindState<Runnable, BindRunType, BoundArgsType...>* bindState)
+        : cb::CallbackBase(bindState)
+    {
+        PolymorphicInvoke f = &bind::BindState<Runnable, BindRunType, BoundArgsType...>::InvokerType::run;
+        m_function = reinterpret_cast<InvokeFunctionStorage>(f);
+    }
+
+    bool equals(const Callback& other) const 
+    {
+        return CallbackBase::equals(other);
+    }
+
+    R run(typename bind::ParamTraits<Args>::ForwardType... args) const 
+    {
+        PolymorphicInvoke f =  reinterpret_cast<PolymorphicInvoke>(m_function);
+        return f(m_bindState.get(), bind::ParamForward(args)...);
+    }
+};
+
+// Syntactic sugar to make Callback<void()> easier to declare since it
+// will be used in a lot of APIs with delayed execution.
+using Closure = Callback<void()>;
+
+} // end namespace tars
+
+#endif

+ 109 - 0
servant/promise/exception.h

@@ -0,0 +1,109 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_EXCEPTION_H_
+#define _TARS_EXCEPTION_H_
+
+#include <exception>
+#include <memory>
+#include <cstring>
+#include <string>
+
+namespace tars {
+    
+class ExceptionBase : public std::exception {
+public:
+    ExceptionBase() {}
+    ~ExceptionBase() throw() override {}
+
+    const char* what() const throw() override
+    {
+        return "exception_base";
+    }
+
+    virtual ExceptionBase* clone() const
+    {
+        return new ExceptionBase(*this);
+    }
+
+    virtual int code() const { return -1; }
+
+    virtual void rethrow() const { throw *this; }
+};
+
+class Exception : public ExceptionBase {
+public:
+    Exception(const std::string& info, const int code = 0)
+        : m_info(info)
+        , m_code(code)
+    {
+        if (code != 0)
+            m_info = m_info + ":" + std::strerror(code);
+    }
+
+    ~Exception() throw() override
+    {
+    }
+
+    const char* what() const throw() override
+    {
+        return m_info.c_str();
+    }
+
+    ExceptionBase* clone() const override 
+    {
+        return new Exception(*this);
+    }
+
+    int code() const override { return m_code; }
+
+    void rethrow() const override { throw *this; }
+
+protected:
+    std::string m_info;
+    int m_code;
+};
+
+using ExceptionPtr = std::shared_ptr<ExceptionBase>;
+
+inline ExceptionPtr currentException()
+{
+    try {
+        throw;
+    } catch (Exception& e) {
+        return ExceptionPtr(e.clone());
+    } catch (ExceptionBase& e) {
+        return ExceptionPtr(e.clone());
+    } catch (std::exception& e) {
+        return ExceptionPtr(new Exception(std::string(e.what())));
+    } catch (...) {
+    }
+
+    return ExceptionPtr(new Exception("unknow_exception"));
+}
+
+inline ExceptionPtr copyException(const std::string& e, int err)
+{
+    try {
+        throw Exception(e, err);
+    } catch (...) {
+        return currentException();
+    }    
+}
+
+} // end namespace tars
+
+#endif

+ 53 - 0
servant/promise/function.h

@@ -0,0 +1,53 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_FUNCTION_H_
+#define _TARS_FUNCTION_H_
+
+#include "promise/template_helper.h"
+#include "promise/type_list.h"
+
+namespace tars {
+
+namespace f {
+
+template <typename R, typename List>
+struct MakeFunctionTypeImpl;
+
+template <typename R, typename... Args>
+struct MakeFunctionTypeImpl<R, tl::TypeList<Args...> > {
+    typedef R Type(Args...);
+};
+
+template <typename R, typename List>
+using MakeFunctionType = typename MakeFunctionTypeImpl<R, List>::Type; 
+
+template <typename F>
+struct ExtractArgsImpl;
+
+template <typename R, typename... Args>
+struct ExtractArgsImpl<R(Args...)> {
+    using Type = tl::TypeList<Args...>;
+};
+
+template <typename F>
+using ExtractArgs = typename ExtractArgsImpl<F>::Type;
+
+} // end namespace f(function)
+
+} // end namespace tars
+
+#endif

+ 806 - 0
servant/promise/promise.h

@@ -0,0 +1,806 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_PROMISE_H_
+#define _TARS_PROMISE_H_
+
+#include <memory>
+#include <mutex>
+#include <condition_variable>
+#include <vector>
+#include "promise/template_helper.h"
+#include "promise/exception.h"
+#include "promise/bind.h"
+
+namespace tars {
+
+// pre-declare future type.
+template <typename T> class Future;
+
+template <typename T> struct IsFutureType : std::false_type {};
+// only Future<T> is a future type.
+template <typename T> struct IsFutureType<Future<T> > : std::true_type {};
+
+// pre-declare promise type.
+template <typename T> class Promise;
+
+namespace promise {
+
+template <typename T> struct UnderlyType { using Type = T; };
+template <typename T> struct UnderlyType<Future<T> > { using Type = T; };
+
+template <typename T> 
+struct FutureTypeTraits {
+    using StorageType = std::shared_ptr<T>;
+    using RValueType = const T&;
+    using LValueType = const T&;
+    using DestType = T&;
+
+    static void init(StorageType& s, RValueType v) 
+    {
+        s.reset(new T(v));
+    }
+
+    static void assign(DestType d, const StorageType& s)
+    {
+        d = *s;
+    }
+};
+
+// since value maybe set in the future, there is no need to check type [const T&]
+template <typename T> 
+struct FutureTypeTraits<T&> {
+    using StorageType = T*; 
+    using RValueType = T&;
+    using LValueType = T&;
+    using DestType = T*&;
+
+    static void init(StorageType& s, RValueType v) 
+    {
+        s = &v;
+    }
+
+    static void assign(DestType d, const StorageType& s)
+    {
+        d = s;
+    }
+};
+
+// void type.
+template <> 
+struct FutureTypeTraits<void> {
+    using RValueType = void;
+    using LValueType = void;
+};
+
+template <typename T>
+class FutureInterface {
+public:
+    using RValueType = typename FutureTypeTraits<T>::RValueType;
+    using LValueType = typename FutureTypeTraits<T>::LValueType;
+    using DestType = typename FutureTypeTraits<T>::DestType;
+    using FutureType = std::shared_ptr<FutureInterface<T> >;
+    using Watcher = Callback<void(const FutureType&)>;
+
+    virtual ~FutureInterface() {}
+
+    virtual bool isDone() const = 0;
+    virtual bool hasValue() const = 0;
+    virtual bool hasException() const = 0;
+    virtual LValueType get() const = 0;
+    virtual bool tryGet(DestType d) const = 0;
+
+    virtual void setValue(RValueType v) = 0;
+    virtual void setException(ExceptionPtr exp) = 0;
+    virtual void appendWacther(const Watcher& watcher) = 0;
+
+protected:
+    FutureInterface() {}
+};
+
+template <> class FutureInterface<void> {
+public:
+    using RValueType = typename FutureTypeTraits<void>::RValueType;
+    using LValueType = typename FutureTypeTraits<void>::LValueType;
+    using FutureType = std::shared_ptr<FutureInterface<void> >;
+    using Watcher = Callback<void(const FutureType&)>;
+
+    virtual ~FutureInterface() {}
+
+    virtual bool isDone() const = 0;
+    virtual bool hasValue() const = 0;
+    virtual bool hasException() const = 0;
+    virtual LValueType get() const  = 0;
+    
+    virtual void set() = 0;
+    virtual void setException(ExceptionPtr exp) = 0;
+    virtual void appendWacther(const Watcher& watcher) = 0;
+
+protected:
+    FutureInterface() {}
+};
+
+template <typename T> 
+class PromptFutureImpl final : public FutureInterface<T>
+                         , public std::enable_shared_from_this<PromptFutureImpl<T> > {
+public:
+    using RValueType = typename FutureInterface<T>::RValueType;
+    using LValueType = typename FutureInterface<T>::LValueType;
+    using DestType = typename FutureInterface<T>::DestType;
+    using Watcher = typename FutureInterface<T>::Watcher; 
+
+    PromptFutureImpl(RValueType v)
+        : m_value()
+        , m_exp()
+    {
+        FutureTypeTraits<T>::init(m_value, v);
+    }
+
+    PromptFutureImpl(ExceptionPtr exp)
+        : m_value()
+        , m_exp(exp)
+    {
+    }
+
+    bool isDone() const override { return true; }
+
+    bool hasValue() const override
+    { 
+        if (m_exp) 
+            return false; 
+        return true;
+    }
+
+    bool hasException() const override
+    {
+        return (!!m_exp);
+    }
+
+    LValueType get() const override
+    {
+        if (m_exp)
+            m_exp->rethrow();
+        return *m_value;
+    }
+
+    bool tryGet(DestType d) const override 
+    {
+        if (m_exp)
+            m_exp->rethrow();
+
+        FutureTypeTraits<T>::assign(d, m_value);
+        return true;
+    }
+
+    void setValue(RValueType v) override
+    {
+        // do not touch this.
+    }
+
+    void setException(ExceptionPtr exp) override
+    {
+        // do not touch this.
+    }
+
+    void appendWacther(const Watcher& watcher) override
+    {
+        try {
+            if (watcher)
+                watcher.run(this->shared_from_this());
+        } catch (...) {
+        }
+    }
+
+private:
+    typename FutureTypeTraits<T>::StorageType m_value;
+    ExceptionPtr m_exp;
+};
+
+template <> class PromptFutureImpl<void> final : public FutureInterface<void>
+                         , public std::enable_shared_from_this<PromptFutureImpl<void> > {
+public:
+    using RValueType = typename FutureInterface<void>::RValueType;
+    using LValueType = typename FutureInterface<void>::LValueType;
+    using Watcher = typename FutureInterface<void>::Watcher; 
+
+    PromptFutureImpl()
+        : m_exp()
+    {
+    }
+
+    PromptFutureImpl(ExceptionPtr exp)
+        : m_exp(exp)
+    {
+    }
+
+    bool isDone() const override { return true; }
+
+    bool hasValue() const override
+    { 
+        if (m_exp) 
+            return false; 
+        return true;
+    }
+
+    bool hasException() const override
+    {
+        return (!!m_exp);
+    }
+
+    LValueType get() const override
+    {
+        if (m_exp)
+            m_exp->rethrow();
+    }
+
+    void set() override
+    {
+        // do not touch this.
+    }
+
+    void setException(ExceptionPtr exp) override
+    {
+        // do not touch this.
+    }
+
+    void appendWacther(const Watcher& watcher) override
+    {
+        try {
+            if (watcher)
+                watcher.run(this->shared_from_this());
+        } catch (...) {
+        }
+    }
+
+private:
+    ExceptionPtr m_exp;
+};
+
+class FutureInternal {
+public:
+    virtual ~FutureInternal() {}
+
+    bool isDone() const 
+    { 
+        std::lock_guard<std::mutex> lock(m_mutex);
+        return m_isDone;
+    }
+
+    bool hasValue() const 
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        return m_isDone && !m_exp;
+    }
+
+    bool hasException() const 
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        return m_isDone && m_exp;
+    }
+
+    void markFinishWithException(const ExceptionPtr& exp) 
+    {
+        {
+            std::lock_guard<std::mutex> lock(m_mutex);
+            if (m_isDone)
+                throw Exception("Duplicated mark finish with exception.");
+
+            m_isDone = true;
+            m_exp = exp;
+        }
+
+        m_cv.notify_all();
+    }
+
+    void wait() const
+    {
+        {
+            std::unique_lock<std::mutex> lock(m_mutex);
+            m_cv.wait(lock, [&]{ return m_isDone; });
+        }
+
+        if (m_exp)
+            m_exp->rethrow();
+    }
+
+protected:
+    FutureInternal()
+        : m_mutex()
+        , m_cv()
+        , m_isDone(false)
+        , m_exp()
+    {
+    }
+
+    mutable std::mutex m_mutex;
+    mutable std::condition_variable m_cv;
+    bool m_isDone;
+    ExceptionPtr m_exp;
+};
+
+template <typename T>
+class FutureImpl : public FutureInterface<T>
+                   , public std::enable_shared_from_this<FutureImpl<T> >
+                   , private FutureInternal {
+public:
+    using RValueType = typename FutureInterface<T>::RValueType;
+    using LValueType = typename FutureInterface<T>::LValueType;
+    using DestType = typename FutureInterface<T>::DestType;
+    using Watcher = typename FutureInterface<T>::Watcher; 
+
+    FutureImpl()
+        : m_value()
+        , m_watchers()
+    {
+    }
+
+    bool isDone() const override { return FutureInternal::isDone(); }
+
+    bool hasValue() const override { return FutureInternal::hasValue(); }
+
+    bool hasException() const override { return FutureInternal::hasException(); }
+
+    LValueType get() const override
+    {
+        wait();
+        return *m_value;
+    }
+
+    bool tryGet(DestType d) const override 
+    {
+        if (!FutureInternal::isDone())
+            return false;
+
+        if (m_exp)
+            m_exp->rethrow();
+
+        FutureTypeTraits<T>::assign(d, m_value);
+        return true;
+    }
+
+    void setValue(RValueType v) override
+    {
+        {
+            // FixMe: move this to FutureInternal.
+            std::lock_guard<std::mutex> lock(m_mutex);
+            if (m_isDone)
+                throw Exception("Duplicated set value.");
+
+            m_isDone = true;
+            FutureTypeTraits<T>::init(m_value, v);
+        }
+
+        m_cv.notify_all();
+        invokeWatchers();
+    }
+
+    void setException(ExceptionPtr exp) override
+    {
+        markFinishWithException(exp);
+        invokeWatchers();
+    }
+
+    void appendWacther(const Watcher& watcher) override
+    {
+        if (!watcher)
+            return;
+
+        if (FutureInternal::isDone()) {
+            try {
+                if (watcher)
+                    watcher.run(this->shared_from_this());
+            } catch (...) {
+            }
+        } else {
+            std::lock_guard<std::mutex> lock(m_mutex);
+            m_watchers.push_back(watcher);
+        }
+    }
+
+protected:
+    void invokeWatchers() 
+    {
+        std::vector<Watcher> watchers;
+        {
+            std::lock_guard<std::mutex> lock(m_mutex);
+            watchers.swap(m_watchers);
+        }
+
+        for (const Watcher& w : watchers) {
+            try {
+                w.run(this->shared_from_this());
+            } catch (...) {
+            }
+        }
+    }
+
+    typename FutureTypeTraits<T>::StorageType m_value;
+    std::vector<Watcher> m_watchers;
+};
+
+template <> class FutureImpl<void> : public FutureInterface<void>
+                   , public std::enable_shared_from_this<FutureImpl<void> >
+                   , private FutureInternal {
+public:
+    using RValueType = typename FutureInterface<void>::RValueType;
+    using LValueType = typename FutureInterface<void>::LValueType;
+    using Watcher = typename FutureInterface<void>::Watcher; 
+
+    FutureImpl()
+        : m_watchers()
+    {
+    }
+
+    bool isDone() const override { return FutureInternal::isDone(); }
+
+    bool hasValue() const override { return FutureInternal::hasValue(); }
+
+    bool hasException() const override { return FutureInternal::hasException(); }
+
+    LValueType get() const override
+    {
+        wait();
+    }
+
+    void set() override
+    {
+        {
+            // FixMe: move this to FutureInternal.
+            std::lock_guard<std::mutex> lock(m_mutex);
+            if (m_isDone)
+                throw Exception("Duplicated set finish.");
+
+            m_isDone = true;
+        }
+
+        m_cv.notify_all();
+        invokeWatchers();
+    }
+
+    void setException(ExceptionPtr exp) override
+    {
+        markFinishWithException(exp);
+        invokeWatchers();
+    }
+
+    void appendWacther(const Watcher& watcher) override
+    {
+        if (!watcher)
+            return;
+
+        if (FutureInternal::isDone()) {
+            try {
+                if (watcher)
+                    watcher.run(this->shared_from_this());
+            } catch (...) {
+            }
+        } else {
+            std::lock_guard<std::mutex> lock(m_mutex);
+            m_watchers.push_back(watcher);
+        }
+    }
+
+protected:
+    void invokeWatchers() 
+    {
+        std::vector<Watcher> watchers;
+        {
+            std::lock_guard<std::mutex> lock(m_mutex);
+            watchers.swap(m_watchers);
+        }
+
+        for (const Watcher& w : watchers) {
+            try {
+                w.run(this->shared_from_this());
+            } catch (...) {
+            }
+        }
+    }
+
+    std::vector<Watcher> m_watchers;
+};
+
+// support sequential watchers.
+template <typename T> class ForwardWatcher;
+
+template <typename R, typename T> class SequentialWatcher {
+    using ValueType = typename UnderlyType<R>::Type;
+    using FuturePtr = std::shared_ptr<FutureInterface<T> >;
+    using Watcher = Callback<R(const Future<T>&)>;
+public:
+    SequentialWatcher(const Watcher& w, const Promise<ValueType>& p)
+        : m_watcher(w)
+        , m_promise(p)
+    {
+    }
+    
+    template <typename U>
+    enable_if_t<std::is_void<U>::value> invoke(const FuturePtr& future)
+    {
+        try {
+            m_watcher.run(future);
+            m_promise.set();
+        } catch (...) {
+            m_promise.setException(currentException());
+        }
+    }
+
+    template <typename U>
+    enable_if_t<!std::is_void<U>::value && !IsFutureType<U>::value> invoke(const FuturePtr& future)
+    {
+        try {
+            m_promise.setValue(m_watcher.run(future));
+        } catch (...) {
+            m_promise.setException(currentException());
+        }
+    }
+
+    template <typename U>
+    enable_if_t<IsFutureType<U>::value> invoke(const FuturePtr& future)
+    {
+        try {
+            // sequential watcher.
+            m_watcher.run(future).then(Bind(&ForwardWatcher<ValueType>::template invoke<ValueType>,
+                        std::make_shared<ForwardWatcher<ValueType> >(m_promise)));
+        } catch (...) {
+            m_promise.setException(currentException());
+        }
+    }
+
+protected:
+    Watcher m_watcher;
+    Promise<ValueType> m_promise;
+};
+
+template <typename R>
+class ForwardWatcher {
+public:
+    ForwardWatcher(const Promise<R>& p)
+        : m_promise(p)
+    {
+    }
+
+    template <typename V>
+    enable_if_t<std::is_void<V>::value> invoke(const Future<V>& future)
+    {
+        try {
+            future.get();
+            m_promise.set();
+        } catch (...) {
+            m_promise.setException(currentException());
+        }
+    }
+
+    template <typename V>
+    enable_if_t<!std::is_void<V>::value> invoke(const Future<V>& future)
+    {
+        try {
+            m_promise.setValue(future.get());
+        } catch (...) {
+            m_promise.setException(currentException());
+        }
+    }
+
+protected:
+    Promise<R> m_promise;
+};
+
+template <typename T>
+class FutureBase {
+public:
+    using LValueType = typename FutureTypeTraits<T>::LValueType;
+
+    FutureBase()
+        : m_future()
+    {
+    }
+
+    FutureBase(ExceptionPtr exp)
+        : m_future(new PromptFutureImpl<T>(exp))
+    {
+    }
+
+    virtual ~FutureBase() {}
+
+    LValueType get() const 
+    {
+        if (!m_future) 
+            throw Exception("future uninitialized");
+        return m_future->get();
+    }
+
+    bool isDone() const 
+    {
+        if (!m_future)
+            return false;
+
+        return m_future->isDone();
+    }
+
+    bool hasValue() const
+    {
+        if (!m_future)
+            return false;
+
+        return m_future->hasValue();
+    }
+
+    bool hasException() const
+    {
+        if (!m_future)
+            return false;
+
+        return m_future->hasException();
+    }
+
+    // safe bool idiom
+    // refer: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool
+    // c++11 standard
+    explicit operator bool() const
+    {
+        return m_future ? true : false;
+    }
+
+protected:
+    using FuturePtr = std::shared_ptr<FutureInterface<T> >;
+
+    FutureBase(const FuturePtr& future)
+        : m_future(future)
+    {
+    }
+
+    FuturePtr m_future;
+};
+
+} // end namespace promise
+
+template <typename T>
+class Future : public promise::FutureBase<T> {
+public:
+    explicit Future(typename promise::FutureTypeTraits<T>::RValueType v)
+        : promise::FutureBase<T>(new promise::PromptFutureImpl<T>(v))
+    {
+    }
+
+    Future(ExceptionPtr exp)
+        : promise::FutureBase<T>(exp)
+    {
+    }
+
+    // can be initialize in tuple.
+    Future() = default;
+
+    ~Future() override {}
+
+    template <typename R>
+    Future<typename promise::UnderlyType<R>::Type> then(const Callback<R(const Future<T>&)>& watcher) 
+    {
+        using ValueType = typename promise::UnderlyType<R>::Type;
+        if (!this->m_future)
+            throw Exception("future uninitialized");
+
+        Promise<ValueType> promise;
+        this->m_future->appendWacther(Bind(&promise::SequentialWatcher<R, T>::template invoke<R>,
+                    std::make_shared<promise::SequentialWatcher<R, T> >(watcher, promise)));
+
+        return promise.getFuture();
+    }
+
+private:
+    using FuturePtr = typename promise::FutureBase<T>::FuturePtr;
+    Future(const FuturePtr& future)
+        : promise::FutureBase<T>(future)
+    {
+    }
+
+    template <typename U, typename V> friend class promise::SequentialWatcher;
+    friend class Promise<T>;
+};
+
+template <> class Future<void> : public promise::FutureBase<void> {
+public:
+    // can be initialize in tuple.
+    Future() = default;
+
+    Future(ExceptionPtr exp)
+        : promise::FutureBase<void>(exp)
+    {
+    }
+
+    ~Future() override {}
+
+    template <typename R>
+    Future<typename promise::UnderlyType<R>::Type> then(const Callback<R(const Future<void>&)>& watcher) 
+    {
+        using ValueType = typename promise::UnderlyType<R>::Type;
+        if (!this->m_future)
+            throw Exception("future uninitialized");
+
+        Promise<ValueType> promise;
+        this->m_future->appendWacther(Bind(&promise::SequentialWatcher<R, void>::template invoke<R>,
+                    std::make_shared<promise::SequentialWatcher<R, void> >(watcher, promise)));
+
+        return promise.getFuture();
+    }
+
+private:
+    using FuturePtr = typename promise::FutureBase<void>::FuturePtr;
+    Future(const FuturePtr& future)
+        : promise::FutureBase<void>(future)
+    {
+    }
+
+    template <typename U, typename V> friend class promise::SequentialWatcher;
+    friend class Promise<void>;
+};
+
+template <typename T>
+class Promise final {
+public:
+    using ValueType = typename promise::UnderlyType<T>::Type;
+    Promise()
+        : m_future(new promise::FutureImpl<ValueType>())
+    {
+    }
+
+    void setValue(typename promise::FutureTypeTraits<T>::RValueType v)
+    {
+        m_future->setValue(v);
+    }
+
+    void setException(const ExceptionPtr& e)
+    {
+        m_future->setException(e);
+    }
+
+    Future<ValueType> getFuture()
+    {
+        return m_future;
+    }
+
+private:
+    std::shared_ptr<promise::FutureInterface<ValueType> > m_future;
+};
+
+template <> class Promise<void> final {
+public:
+    Promise()
+        : m_future(new promise::FutureImpl<void>())
+    {
+    }
+
+    void set()
+    {
+        m_future->set();
+    }
+
+    void setException(const ExceptionPtr& e)
+    {
+        m_future->setException(e);
+    }
+
+    Future<void> getFuture()
+    {
+        return m_future;
+    }
+
+private:
+    std::shared_ptr<promise::FutureInterface<void> > m_future;
+};
+
+} // end namespace tars
+
+#endif

+ 29 - 0
servant/promise/template_helper.h

@@ -0,0 +1,29 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_TEMPLATE_HELPER_H_
+#define _TARS_TEMPLATE_HELPER_H_
+
+#include <type_traits>
+
+namespace tars {
+
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+} // end namespace tars
+
+#endif

+ 128 - 0
servant/promise/type_list.h

@@ -0,0 +1,128 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_TYPE_LIST_H_
+#define _TARS_TYPE_LIST_H_
+
+namespace tars {
+
+namespace tl {
+
+template <typename... Types>
+struct TypeList {};
+
+// get the Nth type in a given type list.
+template <size_t N, typename List>
+struct TypeAtImpl;
+
+template <size_t N, typename T, typename... List>
+struct TypeAtImpl<N, TypeList<T, List...> > 
+                : TypeAtImpl<N-1, TypeList<List...> > {};
+
+template <typename T, typename... List>
+struct TypeAtImpl<0, TypeList<T, List...> > {
+    using Type = T;
+};
+
+// throw error while empty list.
+template <> struct TypeAtImpl<0, TypeList<> > {};
+
+template <size_t N, typename... List>
+using TypeAt = typename TypeAtImpl<N, List...>::Type;
+
+// index of a type in a given type list.
+template <typename T, typename List>
+struct IndexOfImpl;
+
+template <typename T> 
+struct IndexOfImpl<T, TypeList<> > {
+    enum { value = -1 };
+};
+
+template <typename T, typename... List> 
+struct IndexOfImpl<T, TypeList<T, List...> > {
+    enum { value = 0 };
+};
+
+template <typename T, typename U, typename... List>
+struct IndexOfImpl<T, TypeList<U, List...> > {
+private:
+    enum { temp = IndexOfImpl<T, TypeList<List...> >::value };
+public:
+    enum { value = ((temp == -1) ? -1 : (1 + temp)) };
+};
+
+template <typename T, typename List>
+using IndexOf = IndexOfImpl<T, List>;
+
+// drop first N types in a given type list.
+template <size_t N, typename List>
+struct DropTypeListItemImpl;
+
+template <size_t N, typename T, typename... List>
+struct DropTypeListItemImpl<N, TypeList<T, List...> > 
+                : DropTypeListItemImpl<N-1, TypeList<List...> > {};
+
+template <typename T, typename... List>
+struct DropTypeListItemImpl<0, TypeList<T, List...> > {
+    using Type = TypeList<T, List...>;
+};
+
+template <> struct DropTypeListItemImpl<0, TypeList<> > {
+    using Type = TypeList<>;
+};
+
+template <size_t N, typename List>
+using DropTypeListItem = typename DropTypeListItemImpl<N, List>::Type;
+
+// take first N types in a given type list.
+template <size_t N, typename List, typename... TList>
+struct TakeTypeListItemImpl;
+
+template <size_t N, typename T, typename... List, typename... TList>
+struct TakeTypeListItemImpl<N, TypeList<T, List...>, TList...> 
+                : TakeTypeListItemImpl<N-1, TypeList<List...>, TList..., T> {};
+
+template <typename T, typename... List, typename... TList>
+struct TakeTypeListItemImpl<0, TypeList<T, List...>, TList...> {
+    using Type = TypeList<TList...>;
+};
+
+template <typename... TList> 
+struct TakeTypeListItemImpl<0, TypeList<>, TList...> {
+    using Type = TypeList<TList...>;
+};
+
+template <size_t N, typename List>
+using TakeTypeListItem = typename TakeTypeListItemImpl<N, List>::Type;
+
+// concat type lists.
+template <typename List1, typename List2>
+struct ConcatTypeListImpl;
+
+template <typename... ListA, typename... ListB>
+struct ConcatTypeListImpl<TypeList<ListA...>, TypeList<ListB...> > {
+    using Type = TypeList<ListA..., ListB...>;
+};
+
+template <typename List1, typename List2>
+using ConcatTypeList = typename ConcatTypeListImpl<List1, List2>::Type;
+
+} // end namespace tl(type list)
+
+} // end namespace tars
+
+#endif

+ 195 - 0
servant/promise/when_all.h

@@ -0,0 +1,195 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef _TARS_WHEN_ALL_H_
+#define _TARS_WHEN_ALL_H_
+
+#include <vector>
+#include <atomic>
+#include "promise/template_helper.h"
+#include "promise/promise.h"
+
+namespace tars {
+
+namespace wa {
+
+template <typename... Futures>
+struct MakeFuturesStorageImpl {
+    using Type = std::tuple<Futures...>;
+};
+
+template <typename... Futures>
+using MakeFuturesStorage = typename MakeFuturesStorageImpl<
+      typename std::decay<Futures>::type...>::Type;
+
+template <typename... Futures>
+struct FutureList {
+    using StorgeType = MakeFuturesStorage<Futures...>;
+    using FutureType = Future<StorgeType>;
+    using PromiseType = Promise<StorgeType>;
+};
+
+template <typename T>
+class ParallelCallbackBase {
+public:
+    virtual ~ParallelCallbackBase() {}
+
+protected:
+    using PromiseAll = Promise<T>;
+
+    ParallelCallbackBase(const ParallelCallbackBase&) = delete;
+    ParallelCallbackBase(ParallelCallbackBase&&) = delete;
+    ParallelCallbackBase& operator = (const ParallelCallbackBase&) = delete;
+
+    ParallelCallbackBase(const Promise<T>& p, const int totalCount)
+        : m_promise(p)
+        , m_futures()
+        , m_waitCount(totalCount)
+    {
+    }
+
+    
+    PromiseAll m_promise;
+    T m_futures;
+    std::atomic<int> m_waitCount;
+};
+
+template <typename... Futures>
+class ParallelCallback final 
+                : public std::enable_shared_from_this<ParallelCallback<Futures...> >
+                  , public ParallelCallbackBase<
+                  typename FutureList<Futures...>::StorgeType> {
+public:
+    using StorgeType = typename FutureList<Futures...>::StorgeType;
+    using PromiseAll = typename ParallelCallbackBase<StorgeType>::PromiseAll;
+
+    ParallelCallback(const PromiseAll& p)
+        : ParallelCallbackBase<StorgeType>(p, sizeof...(Futures))
+    {
+    }
+
+    ~ParallelCallback() override {}
+
+    void registerCallback()
+    {
+        // do nothing here.
+    }
+
+    template <size_t N, typename T>
+    void registerCallback(T&& f)
+    {
+        f.then(Bind(&ParallelCallback::template onFuture<N>, 
+                    this->shared_from_this()));
+    }
+
+    template <size_t N, typename T, typename... Types>
+    void registerCallback(T&& f, Types&&... fs)
+    {
+        registerCallback<N>(std::forward<T>(f));
+        registerCallback<N+1>(std::forward<Types>(fs)...);
+    }
+
+    template <typename T, typename... Types>
+    void registerCallback(T&& f, Types&&... fs)
+    {
+        registerCallback<0>(std::forward<T>(f), std::forward<Types>(fs)...);
+    }
+
+    template <size_t N>
+    void onFuture(const typename std::tuple_element<N, StorgeType>::type& f) 
+    {
+        std::get<N>(this->m_futures) = f; 
+        int waitCount = this->m_waitCount.fetch_sub(1);
+        if (waitCount > 1)
+            return;
+
+        try {
+            this->m_promise.setValue(this->m_futures);
+        } catch (...) {
+            this->m_promise.setException(currentException());
+        }
+    }
+};
+
+template <typename Futures>
+class ParallelCallback<std::vector<Futures> > final 
+                : public std::enable_shared_from_this<ParallelCallback<std::vector<Futures> > >
+                , public ParallelCallbackBase<std::vector<Futures> > {
+public:
+    using PromiseAll = typename ParallelCallbackBase<std::vector<Futures> >::PromiseAll;
+
+    ParallelCallback(const PromiseAll& p, const size_t count)
+        : ParallelCallbackBase<std::vector<Futures> >(p, count)
+    {
+        this->m_futures.resize(count);
+    }
+
+    ~ParallelCallback() override {}
+
+    void onFuture(const size_t n, const Futures& f) 
+    {
+        this->m_futures[n] = f; 
+        int waitCount = this->m_waitCount.fetch_sub(1);
+        if (waitCount > 1)
+            return;
+
+        try {
+            this->m_promise.setValue(this->m_futures);
+        } catch (...) {
+            this->m_promise.setException(currentException());
+        }
+    }
+};
+
+} // end namespace wa(when all)
+
+template <typename... Futures>
+typename wa::FutureList<Futures...>::FutureType WhenAll(Futures... f)
+{
+    static_assert((sizeof...(Futures) > 1), "TarsWhenAll need at least two features."); 
+
+    using PromiseType = typename wa::FutureList<Futures...>::PromiseType;
+    using WhenAllCallback = wa::ParallelCallback<Futures...>;
+
+    PromiseType p;
+    std::shared_ptr<WhenAllCallback> c = std::make_shared<WhenAllCallback>(p);
+    c->registerCallback(f...);
+    return p.getFuture();
+}
+
+template <typename T>
+Future<std::vector<T> > WhenAll(std::vector<T>& f)
+{
+    static_assert(IsFutureType<T>::value, "T is not a Future type."); 
+
+    using PromiseType = Promise<std::vector<T> >;
+    using WhenAllCallback = wa::ParallelCallback<std::vector<T> >;
+
+    PromiseType p;
+    if (f.empty())
+        p.setValue(std::vector<T>());
+    else {
+        std::shared_ptr<WhenAllCallback> c = std::make_shared<WhenAllCallback>(p, f.size());
+        for (size_t i=0; i<f.size(); ++i)
+            f[i].then(Bind(&WhenAllCallback::onFuture, c, i));
+    }
+
+    return p.getFuture();
+}
+
+} // end namespace tars
+
+#endif

+ 3 - 9
tools/tars2cpp/tars2cpp.cpp

@@ -1801,7 +1801,6 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string&
     return s.str();
 }
 
-/*
 string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
 {
     ostringstream s;
@@ -1834,6 +1833,7 @@ string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
     s << TAB <<"_is.mapBufferSkip("<<pPtr->getId() << "Len);"<<endl;
     return s.str();
 }
+
 bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
 {
     BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
@@ -1861,7 +1861,6 @@ bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
     }
     return false;
 }
-*/
 string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) const
 {
     ostringstream s;
@@ -1922,7 +1921,6 @@ string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) cons
     DEL_TAB;
     s << TAB << "}" << endl;
     s << TAB << endl;
-/*
    //promise异步的函数声明
    string sStruct = pPtr->getId();
     s << TAB << "tars::Future< " << cn <<"PrxCallbackPromise::Promise" << sStruct << "Ptr > promise_async_" << pPtr->getId() << "(";
@@ -1965,7 +1963,7 @@ string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) cons
     DEL_TAB;
     s << TAB << "}" << endl;
     s << endl;
-*/
+
     //协程并行异步的函数声明
     s << TAB << "void coro_" << pPtr->getId() << "(";
     s << cn << "CoroPrxCallbackPtr callback,";
@@ -2254,7 +2252,6 @@ struct SortOperation {
     }
 };
 
-/*
 string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const
 {
     ostringstream s;
@@ -2382,7 +2379,6 @@ string Tars2Cpp::generateDispatchPromiseAsync(const OperationPtr &pPtr, const st
     s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
     return s.str();
 }
-*/
 /******************************InterfacePtr***************************************/
 string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) const
 {
@@ -2488,7 +2484,6 @@ string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) c
 
     s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallback> " << pPtr->getId() << "PrxCallbackPtr;" << endl;
     s << endl;
-/*
 	//生成promise异步回调Proxy
     s << TAB << "//callback of promise async proxy for client" << endl;
     s << TAB << "class " << pPtr->getId() << "PrxCallbackPromise: public tars::ServantProxyCallback" << endl;
@@ -2547,7 +2542,6 @@ string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) c
     s << TAB << "};" << endl;
     s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallbackPromise> " << pPtr->getId() << "PrxCallbackPromisePtr;" << endl;
     s << endl;
-*/
     //生成协程异步回调类,用于并发请求
     s << TAB << "/* callback of coroutine async proxy for client */" << endl;
     s << TAB << "class " << pPtr->getId() << "CoroPrxCallback: public " << pPtr->getId() << "PrxCallback" << endl;
@@ -2939,7 +2933,7 @@ void Tars2Cpp::generateH(const ContextPtr &pPtr) const
         {
             s << "#include \"servant/ServantProxy.h\"" << endl;
             s << "#include \"servant/Servant.h\"" << endl;
-			// s << "#include \"promise/promise.h\"" << endl;
+	    s << "#include \"promise/promise.h\"" << endl;
             break;
         }
     }

+ 6 - 6
tools/tars2cpp/tars2cpp.h

@@ -163,7 +163,7 @@ protected:
      *
      * @return string
      */
-    // string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
+    string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
 
     /**
      *
@@ -171,7 +171,7 @@ protected:
      *
      * @return string
      */
-    // string readUnknown(const TypeIdPtr &pPtr) const;
+//    string readUnknown(const TypeIdPtr &pPtr) const;
     /**
      *
      * @param pPtr
@@ -404,7 +404,7 @@ protected:
      *
      * @return string
      */
-//    string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const;
+    string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const;
 
     /**
      * 生成操作函数调用分发的源码
@@ -413,7 +413,7 @@ protected:
      *
      * @return string
      */
-//    string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
+    string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
 
     /**
      * 生成操作的servant的头文件源码
@@ -490,7 +490,7 @@ protected:
 
     string generateInitValue(const TypeIdPtr &pPtr) const;
 
-//    bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
+    bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
 
 private:
     std::string _baseDir;
@@ -516,4 +516,4 @@ private:
     bool _tarsMaster;
 };
 
-#endif
+#endif

+ 2 - 2
util/include/util/tc_thread_rwlock.h

@@ -81,7 +81,7 @@ protected:
 		void writeLock()
 		{
 			unique_lock<mutex> lck(_mutex);
-			_cond.wait(lck, bind([](const bool *is_w, const size_t *read_c) -> bool
+			_cond.wait(lck, std::bind([](const bool *is_w, const size_t *read_c) -> bool
 			{
 				return false == *is_w && 0 == *read_c;
 			}, &_isWrite, &_readCount));
@@ -195,4 +195,4 @@ typedef TC_RW_RLockT<TC_ThreadRWLocker> TC_ThreadRLock;
 typedef TC_RW_WLockT<TC_ThreadRWLocker> TC_ThreadWLock;
 
 }
-#endif
+#endif