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) add_subdirectory(libservant)
install(DIRECTORY servant DESTINATION include) install(DIRECTORY servant DESTINATION include)
install(DIRECTORY promise DESTINATION include)
install(DIRECTORY tup DESTINATION include) install(DIRECTORY tup DESTINATION include)
install(DIRECTORY jmem DESTINATION include) install(DIRECTORY jmem DESTINATION include)
install(DIRECTORY script DESTINATION . install(DIRECTORY script DESTINATION .

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

View File

@ -163,7 +163,7 @@ protected:
* *
* @return string * @return string
*/ */
// string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const; string promiseReadFrom(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
/** /**
* *
@ -404,7 +404,7 @@ protected:
* *
* @return string * @return string
*/ */
// string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const; string generateHPromiseAsync(const InterfacePtr &pInter, const OperationPtr &pPtr) const;
/** /**
* *
@ -413,7 +413,7 @@ protected:
* *
* @return string * @return string
*/ */
// string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const; string generateDispatchPromiseAsync(const OperationPtr &pPtr, const string &cn) const;
/** /**
* servant的头文件源码 * servant的头文件源码
@ -490,7 +490,7 @@ protected:
string generateInitValue(const TypeIdPtr &pPtr) const; string generateInitValue(const TypeIdPtr &pPtr) const;
// bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const; bool isPromiseDispatchInitValue(const TypeIdPtr &pPtr) const;
private: private:
std::string _baseDir; std::string _baseDir;

View File

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