mirror of
https://gitee.com/TarsCloud/TarsCpp.git
synced 2024-12-22 22:16:38 +08:00
Add promise package.
This commit is contained in:
parent
ff95142392
commit
68e20b7cf6
27
examples/PromiseDemo/AServer/AServant.tars
Normal file
27
examples/PromiseDemo/AServer/AServant.tars
Normal file
@ -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
examples/PromiseDemo/AServer/AServantImp.cpp
Normal file
252
examples/PromiseDemo/AServer/AServantImp.cpp
Normal file
@ -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 ¤t)
|
||||||
|
: _current(current)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BServantCallback(TarsCurrentPtr ¤t, 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 ¤t)
|
||||||
|
: _current(current)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CServantCallback(TarsCurrentPtr ¤t, 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
examples/PromiseDemo/AServer/AServantImp.h
Normal file
62
examples/PromiseDemo/AServer/AServantImp.h
Normal file
@ -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
examples/PromiseDemo/AServer/AServer.cpp
Normal file
57
examples/PromiseDemo/AServer/AServer.cpp
Normal file
@ -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
examples/PromiseDemo/AServer/AServer.h
Normal file
52
examples/PromiseDemo/AServer/AServer.h
Normal file
@ -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
examples/PromiseDemo/AServer/BServant.tars
Normal file
25
examples/PromiseDemo/AServer/BServant.tars
Normal file
@ -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
examples/PromiseDemo/AServer/CServant.tars
Normal file
25
examples/PromiseDemo/AServer/CServant.tars
Normal file
@ -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
examples/PromiseDemo/AServer/makefile
Normal file
12
examples/PromiseDemo/AServer/makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
APP := Test
|
||||||
|
TARGET := AServer
|
||||||
|
CONFIG :=
|
||||||
|
STRIP_FLAG:= N
|
||||||
|
|
||||||
|
INCLUDE +=
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
include /usr/local/tars/cpp/makefile/makefile.tars
|
||||||
|
#-----------------------------------------------------------------------
|
25
examples/PromiseDemo/BServer/BServant.tars
Normal file
25
examples/PromiseDemo/BServer/BServant.tars
Normal file
@ -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
examples/PromiseDemo/BServer/BServantImp.cpp
Normal file
45
examples/PromiseDemo/BServer/BServantImp.cpp
Normal file
@ -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
examples/PromiseDemo/BServer/BServantImp.h
Normal file
40
examples/PromiseDemo/BServer/BServantImp.h
Normal file
@ -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
examples/PromiseDemo/BServer/BServer.cpp
Normal file
57
examples/PromiseDemo/BServer/BServer.cpp
Normal file
@ -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
examples/PromiseDemo/BServer/BServer.h
Normal file
52
examples/PromiseDemo/BServer/BServer.h
Normal file
@ -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
examples/PromiseDemo/BServer/makefile
Normal file
11
examples/PromiseDemo/BServer/makefile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
APP := Test
|
||||||
|
TARGET := BServer
|
||||||
|
CONFIG :=
|
||||||
|
STRIP_FLAG:= N
|
||||||
|
INCLUDE +=
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
include /usr/local/tars/cpp/makefile/makefile.tars
|
||||||
|
#-----------------------------------------------------------------------
|
25
examples/PromiseDemo/CServer/CServant.tars
Normal file
25
examples/PromiseDemo/CServer/CServant.tars
Normal file
@ -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
examples/PromiseDemo/CServer/CServantImp.cpp
Normal file
45
examples/PromiseDemo/CServer/CServantImp.cpp
Normal file
@ -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
examples/PromiseDemo/CServer/CServantImp.h
Normal file
40
examples/PromiseDemo/CServer/CServantImp.h
Normal file
@ -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
examples/PromiseDemo/CServer/CServer.cpp
Normal file
57
examples/PromiseDemo/CServer/CServer.cpp
Normal file
@ -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
examples/PromiseDemo/CServer/CServer.h
Normal file
53
examples/PromiseDemo/CServer/CServer.h
Normal file
@ -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
examples/PromiseDemo/CServer/makefile
Normal file
11
examples/PromiseDemo/CServer/makefile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#-----------------------------------------------------------------------
|
||||||
|
APP := Test
|
||||||
|
TARGET := CServer
|
||||||
|
CONFIG :=
|
||||||
|
STRIP_FLAG:= N
|
||||||
|
|
||||||
|
INCLUDE +=
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
include /usr/local/tars/cpp/makefile/makefile.tars
|
||||||
|
#-----------------------------------------------------------------------
|
138
examples/PromiseDemo/Client/main.cpp
Normal file
138
examples/PromiseDemo/Client/main.cpp
Normal file
@ -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
examples/PromiseDemo/Client/makefile
Normal file
13
examples/PromiseDemo/Client/makefile
Normal file
@ -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
examples/PromiseDemo/README.md
Normal file
6
examples/PromiseDemo/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
该工程是Tars promise编程示例的代码
|
||||||
|
|
||||||
|
|
||||||
|
目录名称 |功能
|
||||||
|
-----------------|----------------
|
||||||
|
AServer | promise编程的示例程序,用promsie方式去并行和串行访问BServer和CServer
|
@ -67,6 +67,7 @@ add_subdirectory(tup)
|
|||||||
add_subdirectory(libservant)
|
add_subdirectory(libservant)
|
||||||
|
|
||||||
install(DIRECTORY servant DESTINATION include)
|
install(DIRECTORY servant DESTINATION include)
|
||||||
|
install(DIRECTORY promise DESTINATION include)
|
||||||
install(DIRECTORY tup DESTINATION include)
|
install(DIRECTORY tup DESTINATION include)
|
||||||
install(DIRECTORY jmem DESTINATION include)
|
install(DIRECTORY jmem DESTINATION include)
|
||||||
install(DIRECTORY script DESTINATION .
|
install(DIRECTORY script DESTINATION .
|
||||||
|
50
servant/promise/bind.h
Normal file
50
servant/promise/bind.h
Normal file
@ -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
servant/promise/bind_internal.h
Normal file
316
servant/promise/bind_internal.h
Normal file
@ -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
servant/promise/callback.h
Normal file
119
servant/promise/callback.h
Normal file
@ -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
servant/promise/exception.h
Normal file
109
servant/promise/exception.h
Normal file
@ -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
servant/promise/function.h
Normal file
53
servant/promise/function.h
Normal file
@ -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
servant/promise/promise.h
Normal file
806
servant/promise/promise.h
Normal file
@ -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
servant/promise/template_helper.h
Normal file
29
servant/promise/template_helper.h
Normal file
@ -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
servant/promise/type_list.h
Normal file
128
servant/promise/type_list.h
Normal file
@ -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
servant/promise/when_all.h
Normal file
195
servant/promise/when_all.h
Normal file
@ -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
|
@ -1801,7 +1801,6 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string&
|
|||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
|
string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
|
||||||
{
|
{
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
@ -1834,6 +1833,7 @@ string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
|
|||||||
s << TAB <<"_is.mapBufferSkip("<<pPtr->getId() << "Len);"<<endl;
|
s << TAB <<"_is.mapBufferSkip("<<pPtr->getId() << "Len);"<<endl;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
|
bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
|
||||||
{
|
{
|
||||||
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
|
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
|
||||||
@ -1861,7 +1861,6 @@ bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) const
|
string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) const
|
||||||
{
|
{
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
@ -1922,7 +1921,6 @@ string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) cons
|
|||||||
DEL_TAB;
|
DEL_TAB;
|
||||||
s << TAB << "}" << endl;
|
s << TAB << "}" << endl;
|
||||||
s << TAB << endl;
|
s << TAB << endl;
|
||||||
/*
|
|
||||||
//promise异步的函数声明
|
//promise异步的函数声明
|
||||||
string sStruct = pPtr->getId();
|
string sStruct = pPtr->getId();
|
||||||
s << TAB << "tars::Future< " << cn <<"PrxCallbackPromise::Promise" << sStruct << "Ptr > promise_async_" << 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;
|
DEL_TAB;
|
||||||
s << TAB << "}" << endl;
|
s << TAB << "}" << endl;
|
||||||
s << endl;
|
s << endl;
|
||||||
*/
|
|
||||||
//协程并行异步的函数声明
|
//协程并行异步的函数声明
|
||||||
s << TAB << "void coro_" << pPtr->getId() << "(";
|
s << TAB << "void coro_" << pPtr->getId() << "(";
|
||||||
s << cn << "CoroPrxCallbackPtr callback,";
|
s << cn << "CoroPrxCallbackPtr callback,";
|
||||||
@ -2254,7 +2252,6 @@ struct SortOperation {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const
|
string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const
|
||||||
{
|
{
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
@ -2382,7 +2379,6 @@ string Tars2Cpp::generateDispatchPromiseAsync(const OperationPtr &pPtr, const st
|
|||||||
s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
|
s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/******************************InterfacePtr***************************************/
|
/******************************InterfacePtr***************************************/
|
||||||
string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) const
|
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 << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallback> " << pPtr->getId() << "PrxCallbackPtr;" << endl;
|
||||||
s << endl;
|
s << endl;
|
||||||
/*
|
|
||||||
//生成promise异步回调Proxy
|
//生成promise异步回调Proxy
|
||||||
s << TAB << "//callback of promise async proxy for client" << endl;
|
s << TAB << "//callback of promise async proxy for client" << endl;
|
||||||
s << TAB << "class " << pPtr->getId() << "PrxCallbackPromise: public tars::ServantProxyCallback" << 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 << "};" << endl;
|
||||||
s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallbackPromise> " << pPtr->getId() << "PrxCallbackPromisePtr;" << endl;
|
s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallbackPromise> " << pPtr->getId() << "PrxCallbackPromisePtr;" << endl;
|
||||||
s << endl;
|
s << endl;
|
||||||
*/
|
|
||||||
//生成协程异步回调类,用于并发请求
|
//生成协程异步回调类,用于并发请求
|
||||||
s << TAB << "/* callback of coroutine async proxy for client */" << endl;
|
s << TAB << "/* callback of coroutine async proxy for client */" << endl;
|
||||||
s << TAB << "class " << pPtr->getId() << "CoroPrxCallback: public " << pPtr->getId() << "PrxCallback" << 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/ServantProxy.h\"" << endl;
|
||||||
s << "#include \"servant/Servant.h\"" << endl;
|
s << "#include \"servant/Servant.h\"" << endl;
|
||||||
// s << "#include \"promise/promise.h\"" << endl;
|
s << "#include \"promise/promise.h\"" << endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ protected:
|
|||||||
*
|
*
|
||||||
* @return string
|
* @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
|
* @return string
|
||||||
*/
|
*/
|
||||||
// string readUnknown(const TypeIdPtr &pPtr) const;
|
// string readUnknown(const TypeIdPtr &pPtr) const;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param pPtr
|
* @param pPtr
|
||||||
@ -404,7 +404,7 @@ protected:
|
|||||||
*
|
*
|
||||||
* @return string
|
* @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
|
* @return string
|
||||||
*/
|
*/
|
||||||
// string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
|
string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成操作的servant的头文件源码
|
* 生成操作的servant的头文件源码
|
||||||
@ -490,7 +490,7 @@ protected:
|
|||||||
|
|
||||||
string generateInitValue(const TypeIdPtr &pPtr) const;
|
string generateInitValue(const TypeIdPtr &pPtr) const;
|
||||||
|
|
||||||
// bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
|
bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _baseDir;
|
std::string _baseDir;
|
||||||
@ -516,4 +516,4 @@ private:
|
|||||||
bool _tarsMaster;
|
bool _tarsMaster;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -81,7 +81,7 @@ protected:
|
|||||||
void writeLock()
|
void writeLock()
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lck(_mutex);
|
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;
|
return false == *is_w && 0 == *read_c;
|
||||||
}, &_isWrite, &_readCount));
|
}, &_isWrite, &_readCount));
|
||||||
@ -195,4 +195,4 @@ typedef TC_RW_RLockT<TC_ThreadRWLocker> TC_ThreadRLock;
|
|||||||
typedef TC_RW_WLockT<TC_ThreadRWLocker> TC_ThreadWLock;
|
typedef TC_RW_WLockT<TC_ThreadRWLocker> TC_ThreadWLock;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user