Add promise package.

This commit is contained in:
julianyang 2021-09-16 18:56:19 +08:00 committed by ruanshudong
parent ff95142392
commit 68e20b7cf6
36 changed files with 2947 additions and 17 deletions

View 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);
};
};

View 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 &current)
: _current(current)
{}
BServantCallback(TarsCurrentPtr &current, const tars::Promise<std::string> &promise)
: _current(current)
, _promise(promise)
{}
void callback_queryResult(tars::Int32 ret, const std::string &sOut)
{
if(ret == 0)
{
_promise.setValue(sOut);
}
else
{
handExp("callback_queryResult", ret);
}
}
void callback_queryResult_exception(tars::Int32 ret)
{
handExp("callback_queryResult_exception", ret);
}
private:
void handExp(const std::string &sFuncName, tars::Int32 ret)
{
string s("sFuncName:");
s += sFuncName;
s += "|ret:";
s += TC_Common::tostr(ret);
_promise.setException(tars::copyException(s, -1));
TLOGDEBUG("ServerPrxCallback handExp:" << s << endl);
}
private:
TarsCurrentPtr _current;
tars::Promise<std::string> _promise;
};
//////////////////////////////////////////////////////
class CServantCallback : public CServantPrxCallback
{
public:
CServantCallback(TarsCurrentPtr &current)
: _current(current)
{}
CServantCallback(TarsCurrentPtr &current, const tars::Promise<std::string> &promise)
: _current(current)
, _promise(promise)
{}
void callback_queryResult(tars::Int32 ret, const std::string &sOut)
{
if(ret == 0)
{
_promise.setValue(sOut);
}
else
{
handExp("callback_queryResult", ret);
}
}
void callback_queryResult_exception(tars::Int32 ret)
{
handExp("callback_queryResult_exception", ret);
}
private:
void handExp(const std::string &sFuncName, tars::Int32 ret)
{
string s("sFuncName:");
s += sFuncName;
s += "|ret:";
s += TC_Common::tostr(ret);
_promise.setException(tars::copyException(s, -1));
TLOGDEBUG("ServerPrxCallback handExp:" << s << endl);
}
private:
TarsCurrentPtr _current;
tars::Promise<std::string> _promise;
};
//////////////////////////////////////////////////////
tars::Future<std::string> sendBReq(BServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current)
{
tars::Promise<std::string> promise;
Test::BServantPrxCallbackPtr cb = new BServantCallback(current, promise);
prx->async_queryResult(cb, sIn);
return promise.getFuture();
}
//////////////////////////////////////////////////////
tars::Future<std::string> sendCReq(CServantPrx prx, const std::string& sIn, tars::TarsCurrentPtr current)
{
tars::Promise<std::string> promise;
Test::CServantPrxCallbackPtr cb = new CServantCallback(current, promise);
prx->async_queryResult(cb, sIn);
return promise.getFuture();
}
//////////////////////////////////////////////////////
tars::Future<std::string> handleBRspAndSendCReq(CServantPrx prx, TarsCurrentPtr current, const tars::Future<std::string>& future)
{
std::string sResult("");
std::string sException("");
try
{
sResult = future.get();
return sendCReq(prx, sResult, current);
}
catch (exception& e)
{
TLOGDEBUG("Exception:" << e.what() << endl);
sException = e.what();
}
tars::Promise<std::string> promise;
promise.setValue(sException);
return promise.getFuture();
}
//////////////////////////////////////////////////////
int handleCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::string>& future)
{
int ret = 0;
std::string sResult("");
try
{
sResult = future.get();
}
catch (exception& e)
{
ret = -1;
sResult = e.what();
TLOGDEBUG("Exception:" << e.what() << endl);
}
AServant::async_response_queryResultSerial(current, ret, sResult);
return 0;
}
//////////////////////////////////////////////////////
int handleBCRspAndReturnClient(TarsCurrentPtr current, const tars::Future<std::tuple<tars::Future<std::string>, tars::Future<std::string> > >& allFuture)
{
int ret = 0;
std::string sResult("");
try
{
const std::tuple<tars::Future<std::string>, tars::Future<std::string> >& tupleFuture = allFuture.get();
std::string sResult1 = std::get<0>(tupleFuture).get();
std::string sResult2 = std::get<1>(tupleFuture).get();
sResult = sResult1;
sResult += "|";
sResult += sResult2;
}
catch (exception& e)
{
ret = -1;
sResult = e.what();
TLOGDEBUG("Exception:" << e.what() << endl);
}
AServant::async_response_queryResultParallel(current, ret, sResult);
return 0;
}
//////////////////////////////////////////////////////
void AServantImp::initialize()
{
//initialize servant here:
//...
_pPrxB = Application::getCommunicator()->stringToProxy<BServantPrx>("Test.BServer.BServantObj");
_pPrxC = Application::getCommunicator()->stringToProxy<CServantPrx>("Test.CServer.CServantObj");
}
//////////////////////////////////////////////////////
void AServantImp::destroy()
{
}
//////////////////////////////////////////////////////
tars::Int32 AServantImp::queryResultSerial(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
{
current->setResponse(false);
tars::Future<std::string> f = sendBReq(_pPrxB, sIn, current);
f.then(tars::Bind(&handleBRspAndSendCReq, _pPrxC, current)).then(tars::Bind(&handleCRspAndReturnClient, current));
return 0;
}
//////////////////////////////////////////////////////
tars::Int32 AServantImp::queryResultParallel(const std::string& sIn, std::string &sOut, tars::TarsCurrentPtr current)
{
current->setResponse(false);
tars::Future<std::string> f1 = sendBReq(_pPrxB, sIn, current);
tars::Future<std::string> f2 = sendCReq(_pPrxC, sIn, current);
tars::Future<std::tuple<tars::Future<std::string>, tars::Future<std::string> > > f_all = tars::WhenAll(f1, f2);
f_all.then(tars::Bind(&handleBCRspAndReturnClient, current));
return 0;
}

View 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

View 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;
}
/////////////////////////////////////////////////////////////////

View 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

View 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);
};
};

View 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);
};
};

View File

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

View 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);
};
};

View 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;
}

View 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

View 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;
}
/////////////////////////////////////////////////////////////////

View 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

View File

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

View 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);
};
};

View 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;
}

View 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

View 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;
}
/////////////////////////////////////////////////////////////////

View 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

View File

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

View 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;
}

View 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
#-----------------------------------------------------------------------

View File

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

View File

@ -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
View 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

View 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
View 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
View 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

View 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
View 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

View 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
View 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
View 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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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));