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)
|
||||
|
||||
install(DIRECTORY servant DESTINATION include)
|
||||
install(DIRECTORY promise DESTINATION include)
|
||||
install(DIRECTORY tup DESTINATION include)
|
||||
install(DIRECTORY jmem DESTINATION include)
|
||||
install(DIRECTORY script DESTINATION .
|
||||
|
50
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();
|
||||
}
|
||||
|
||||
/*
|
||||
string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
|
||||
{
|
||||
ostringstream s;
|
||||
@ -1834,6 +1833,7 @@ string Tars2Cpp::promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire) const
|
||||
s << TAB <<"_is.mapBufferSkip("<<pPtr->getId() << "Len);"<<endl;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
|
||||
{
|
||||
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
|
||||
@ -1861,7 +1861,6 @@ bool Tars2Cpp::isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) const
|
||||
{
|
||||
ostringstream s;
|
||||
@ -1922,7 +1921,6 @@ string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) cons
|
||||
DEL_TAB;
|
||||
s << TAB << "}" << endl;
|
||||
s << TAB << endl;
|
||||
/*
|
||||
//promise异步的函数声明
|
||||
string sStruct = pPtr->getId();
|
||||
s << TAB << "tars::Future< " << cn <<"PrxCallbackPromise::Promise" << sStruct << "Ptr > promise_async_" << pPtr->getId() << "(";
|
||||
@ -1965,7 +1963,7 @@ string Tars2Cpp::generateHAsync(const OperationPtr& pPtr, const string& cn) cons
|
||||
DEL_TAB;
|
||||
s << TAB << "}" << endl;
|
||||
s << endl;
|
||||
*/
|
||||
|
||||
//协程并行异步的函数声明
|
||||
s << TAB << "void coro_" << pPtr->getId() << "(";
|
||||
s << cn << "CoroPrxCallbackPtr callback,";
|
||||
@ -2254,7 +2252,6 @@ struct SortOperation {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const
|
||||
{
|
||||
ostringstream s;
|
||||
@ -2382,7 +2379,6 @@ string Tars2Cpp::generateDispatchPromiseAsync(const OperationPtr &pPtr, const st
|
||||
s << TAB << "return tars::TARSSERVERSUCCESS;" << endl;
|
||||
return s.str();
|
||||
}
|
||||
*/
|
||||
/******************************InterfacePtr***************************************/
|
||||
string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) const
|
||||
{
|
||||
@ -2488,7 +2484,6 @@ string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) c
|
||||
|
||||
s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallback> " << pPtr->getId() << "PrxCallbackPtr;" << endl;
|
||||
s << endl;
|
||||
/*
|
||||
//生成promise异步回调Proxy
|
||||
s << TAB << "//callback of promise async proxy for client" << endl;
|
||||
s << TAB << "class " << pPtr->getId() << "PrxCallbackPromise: public tars::ServantProxyCallback" << endl;
|
||||
@ -2547,7 +2542,6 @@ string Tars2Cpp::generateH(const InterfacePtr &pPtr, const NamespacePtr &nPtr) c
|
||||
s << TAB << "};" << endl;
|
||||
s << TAB << "typedef tars::TC_AutoPtr<" << pPtr->getId() << "PrxCallbackPromise> " << pPtr->getId() << "PrxCallbackPromisePtr;" << endl;
|
||||
s << endl;
|
||||
*/
|
||||
//生成协程异步回调类,用于并发请求
|
||||
s << TAB << "/* callback of coroutine async proxy for client */" << endl;
|
||||
s << TAB << "class " << pPtr->getId() << "CoroPrxCallback: public " << pPtr->getId() << "PrxCallback" << endl;
|
||||
@ -2939,7 +2933,7 @@ void Tars2Cpp::generateH(const ContextPtr &pPtr) const
|
||||
{
|
||||
s << "#include \"servant/ServantProxy.h\"" << endl;
|
||||
s << "#include \"servant/Servant.h\"" << endl;
|
||||
// s << "#include \"promise/promise.h\"" << endl;
|
||||
s << "#include \"promise/promise.h\"" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ protected:
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
// string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
|
||||
string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -171,7 +171,7 @@ protected:
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
// string readUnknown(const TypeIdPtr &pPtr) const;
|
||||
// string readUnknown(const TypeIdPtr &pPtr) const;
|
||||
/**
|
||||
*
|
||||
* @param pPtr
|
||||
@ -404,7 +404,7 @@ protected:
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
// string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const;
|
||||
string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const;
|
||||
|
||||
/**
|
||||
* 生成操作函数调用分发的源码
|
||||
@ -413,7 +413,7 @@ protected:
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
// string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
|
||||
string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
|
||||
|
||||
/**
|
||||
* 生成操作的servant的头文件源码
|
||||
@ -490,7 +490,7 @@ protected:
|
||||
|
||||
string generateInitValue(const TypeIdPtr &pPtr) const;
|
||||
|
||||
// bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
|
||||
bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
|
||||
|
||||
private:
|
||||
std::string _baseDir;
|
||||
@ -516,4 +516,4 @@ private:
|
||||
bool _tarsMaster;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -81,7 +81,7 @@ protected:
|
||||
void writeLock()
|
||||
{
|
||||
unique_lock<mutex> lck(_mutex);
|
||||
_cond.wait(lck, bind([](const bool *is_w, const size_t *read_c) -> bool
|
||||
_cond.wait(lck, std::bind([](const bool *is_w, const size_t *read_c) -> bool
|
||||
{
|
||||
return false == *is_w && 0 == *read_c;
|
||||
}, &_isWrite, &_readCount));
|
||||
@ -195,4 +195,4 @@ typedef TC_RW_RLockT<TC_ThreadRWLocker> TC_ThreadRLock;
|
||||
typedef TC_RW_WLockT<TC_ThreadRWLocker> TC_ThreadWLock;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user