forked from mindspore-Ecosystem/mindspore
Add unified runtime from multi backend
This commit is contained in:
parent
d7f8743486
commit
56ece6fa58
|
@ -2,6 +2,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|||
include_directories(${CMAKE_BINARY_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/mindspore/core)
|
||||
add_subdirectory(gvar)
|
||||
if(NOT(CMAKE_SYSTEM_NAME MATCHES "Windows"))
|
||||
add_subdirectory(mindrt)
|
||||
endif()
|
||||
message("************ build core ***************")
|
||||
|
||||
|
||||
|
@ -18,7 +21,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -DHAVE_SNPRINTF")
|
||||
add_compile_definitions(BUILDING_DLL)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuser-defined-warnings -Winconsistent-missing-override -Wno-delete-non-abstract-non-virtual-dtor")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
|
||||
-Wuser-defined-warnings -Winconsistent-missing-override -Wno-delete-non-abstract-non-virtual-dtor")
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${CORE_SRC_LIST} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_CORE)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/)
|
||||
|
||||
file(GLOB MINDRT_SRC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/actor/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/async/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/evloop/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/timer/*.cc
|
||||
)
|
||||
|
||||
|
||||
add_library(mindrt_mid OBJECT ${MINDRT_SRC})
|
||||
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_ACTOR_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_ACTOR_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "actor/msg.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class ActorBase;
|
||||
class ActorMgr;
|
||||
class ActorPolicy;
|
||||
|
||||
using ActorReference = std::shared_ptr<ActorBase>;
|
||||
|
||||
// should be at least greater than 1
|
||||
constexpr uint32_t MAX_ACTOR_RECORD_SIZE = 3;
|
||||
|
||||
class ActorBase {
|
||||
public:
|
||||
inline const AID &GetAID() const { return id; }
|
||||
|
||||
inline void AddMsgRecord(const std::string &msgName) {
|
||||
recordNextPoint++;
|
||||
uint32_t startPoint = recordNextPoint % MAX_ACTOR_RECORD_SIZE;
|
||||
msgRecords[startPoint] = msgName;
|
||||
}
|
||||
|
||||
inline void PrintMsgRecord() {
|
||||
uint32_t startPoint = recordNextPoint % MAX_ACTOR_RECORD_SIZE;
|
||||
for (uint32_t i = 0; i < MAX_ACTOR_RECORD_SIZE; i++) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "Actor message dumps:%s",
|
||||
"actor:%s,msg:%s", id.Name().c_str(), msgRecords[startPoint].c_str());
|
||||
startPoint = (startPoint + MAX_ACTOR_RECORD_SIZE - 1) % MAX_ACTOR_RECORD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
explicit ActorBase(const std::string &name);
|
||||
virtual ~ActorBase();
|
||||
|
||||
// send MessageBase message to the actor.
|
||||
int Send(const AID &to, std::unique_ptr<MessageBase> msg);
|
||||
|
||||
// send string message to the actor
|
||||
int Send(const AID &to, std::string &&name, std::string &&msg, bool remoteLink = false,
|
||||
bool isExactNotRemote = false);
|
||||
|
||||
// get output buffer size for flow control
|
||||
uint64_t GetOutBufSize(const AID &to);
|
||||
|
||||
// get input buffer size for flow control
|
||||
uint64_t GetInBufSize(const AID &to);
|
||||
|
||||
// set record send/receive message package size
|
||||
int AddRuleUdp(const std::string &peer, int recordNum);
|
||||
|
||||
// delete the send/receive message package size
|
||||
void DelRuleUdp(const std::string &peer, bool outputLog);
|
||||
|
||||
protected:
|
||||
using ActorFunction = std::function<void(std::unique_ptr<MessageBase> &msg)>;
|
||||
|
||||
// install KMSG handler . This method will be called before the actor start to run.
|
||||
virtual void Init() {}
|
||||
|
||||
// This method will be called before the actor start to terminate.
|
||||
virtual void Finalize() {}
|
||||
|
||||
// KHTTPMsg handler
|
||||
virtual void HandleHttp(std::unique_ptr<MessageBase> msg) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"ACTOR (%s) HandleHttp() is not implemented", "a=%s", id.Name().c_str());
|
||||
}
|
||||
|
||||
// KLOCALMsg handler
|
||||
virtual void HandleLocalMsg(std::unique_ptr<MessageBase> msg) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"ACTOR (%s) HandleLocalMsg() is not implemented.", "a=%s", id.Name().c_str());
|
||||
}
|
||||
|
||||
// The link is closed.
|
||||
virtual void Exited(const AID &actor) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"ACTOR (%s) Exited() is not implemented. ", "a=%s", id.Name().c_str());
|
||||
}
|
||||
|
||||
// Filter the KMSG
|
||||
virtual bool Filter(const std::unique_ptr<MessageBase> &msg) { return false; }
|
||||
|
||||
// register the message handle
|
||||
void Receive(const std::string &msgName, ActorFunction &&func);
|
||||
|
||||
// register the message handle. It will be discarded.
|
||||
template <typename T>
|
||||
void Receive(const std::string &msgName, void (T::*method)(mindspore::AID, std::string &&, std::string &&)) {
|
||||
ActorFunction func = std::bind(&BehaviorBase1<T>, static_cast<T *>(this), method, std::placeholders::_1);
|
||||
Receive(msgName, std::move(func));
|
||||
}
|
||||
|
||||
// register the message handle
|
||||
template <typename T>
|
||||
void Receive(const std::string &msgName, void (T::*method)(const mindspore::AID &, std::string &&, std::string &&)) {
|
||||
ActorFunction func = std::bind(&BehaviorBase<T>, static_cast<T *>(this), method, std::placeholders::_1);
|
||||
Receive(msgName, std::move(func));
|
||||
return;
|
||||
}
|
||||
|
||||
// register the message handle, for kmsg-udp message
|
||||
template <typename T>
|
||||
void ReceiveUdp(const std::string &msgName,
|
||||
void (T::*method)(const mindspore::AID &, std::string &&, std::string &&)) {
|
||||
ActorFunction func = std::bind(&BehaviorBaseForUdp<T>, static_cast<T *>(this), method, std::placeholders::_1);
|
||||
Receive(msgName, std::move(func));
|
||||
return;
|
||||
}
|
||||
|
||||
// Link the remote actor
|
||||
int Link(const AID &to);
|
||||
|
||||
// Unlink the remote actor
|
||||
int UnLink(const AID &to);
|
||||
|
||||
// Reconnect to the remote actor
|
||||
int Reconnect(const AID &to);
|
||||
|
||||
void Terminate();
|
||||
void Await();
|
||||
|
||||
private:
|
||||
friend class ActorMgr;
|
||||
friend class ActorThread;
|
||||
|
||||
// KMSG Msg Handler
|
||||
virtual void HandlekMsg(std::unique_ptr<MessageBase> &msg);
|
||||
|
||||
template <typename T>
|
||||
static void BehaviorBase(T *t, void (T::*method)(const mindspore::AID &, std::string &&, std::string &&),
|
||||
std::unique_ptr<MessageBase> &msg) {
|
||||
if (msg->type != MessageBase::Type::KMSG) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Drop non-tcp message: %s",
|
||||
"from:%s,to:%s,name:%s", std::string(msg->from).c_str(), std::string(msg->to).c_str(),
|
||||
msg->name.c_str());
|
||||
return;
|
||||
}
|
||||
(t->*method)(msg->from, std::move(msg->name), std::move(msg->body));
|
||||
}
|
||||
|
||||
// register the message handle. It will be discarded.
|
||||
template <typename T>
|
||||
static void BehaviorBase1(T *t, void (T::*method)(mindspore::AID, std::string &&, std::string &&),
|
||||
std::unique_ptr<MessageBase> &msg) {
|
||||
if (msg->type != MessageBase::Type::KMSG) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Drop non-tcp message: %s",
|
||||
"from:%s,to:%s,name:%s", std::string(msg->from).c_str(), std::string(msg->to).c_str(),
|
||||
msg->name.c_str());
|
||||
return;
|
||||
}
|
||||
(t->*method)(msg->from, std::move(msg->name), std::move(msg->body));
|
||||
}
|
||||
|
||||
// register the udp message handle. Use this closure function to drop non-udp messages
|
||||
template <typename T>
|
||||
static void BehaviorBaseForUdp(T *t, void (T::*method)(const mindspore::AID &, std::string &&, std::string &&),
|
||||
std::unique_ptr<MessageBase> &msg) {
|
||||
if (msg->type != MessageBase::Type::KUDP) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Drop non-udp message: %s",
|
||||
"from:%s,to:%s,name:%s", std::string(msg->from).c_str(), std::string(msg->to).c_str(),
|
||||
msg->name.c_str());
|
||||
return;
|
||||
}
|
||||
(t->*method)(msg->from, std::move(msg->name), std::move(msg->body));
|
||||
}
|
||||
|
||||
void Run();
|
||||
void Quit();
|
||||
int EnqueMessage(std::unique_ptr<MessageBase> msg);
|
||||
|
||||
void Spawn(std::shared_ptr<ActorBase> &actor, std::unique_ptr<ActorPolicy> actorThread);
|
||||
void SetRunningStatus(bool start);
|
||||
|
||||
std::unique_ptr<ActorPolicy> actorThread;
|
||||
|
||||
AID id;
|
||||
std::map<std::string, ActorFunction> actionFunctions;
|
||||
std::mutex waiterLock;
|
||||
|
||||
std::string msgRecords[MAX_ACTOR_RECORD_SIZE];
|
||||
uint32_t recordNextPoint = 0;
|
||||
};
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_ACTORAPP_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_ACTORAPP_H
|
||||
|
||||
#include "actor/actor.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class MessageLocal : public MessageBase {
|
||||
public:
|
||||
MessageLocal(const AID &from, const AID &to, const std::string &name, void *aPtr)
|
||||
: MessageBase(from, to, name, "LocalMsg", Type::KLOCAL), ptr(aPtr) {}
|
||||
~MessageLocal() {}
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
class AppActor : public ActorBase {
|
||||
public:
|
||||
typedef std::function<void(std::unique_ptr<MessageBase>)> APPBehavior;
|
||||
|
||||
AppActor(const std::string &name) : ActorBase(name) {}
|
||||
~AppActor() {}
|
||||
|
||||
inline int Send(const AID &to, std::unique_ptr<MessageBase> msg) { return ActorBase::Send(to, std::move(msg)); }
|
||||
// send T message to the actor
|
||||
template <typename M>
|
||||
int Send(const std::string &to, const std::string &msgName, std::unique_ptr<M> msg) {
|
||||
std::unique_ptr<MessageLocal> localMsg(new (std::nothrow) MessageLocal(GetAID(), to, msgName, msg.release()));
|
||||
BUS_OOM_EXIT(localMsg);
|
||||
return Send(to, std::move(localMsg));
|
||||
}
|
||||
|
||||
// register the message handle
|
||||
template <typename T, typename M>
|
||||
void Receive(const std::string &msgName, void (T::*method)(const AID &, std::unique_ptr<M>)) {
|
||||
APPBehavior behavior = std::bind(&BehaviorBase<T, M>, static_cast<T *>(this), method, std::placeholders::_1);
|
||||
|
||||
if (appBehaviors.find(msgName) != appBehaviors.end()) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "ACTOR msgName conflict:%s",
|
||||
"a=%s,msg=%s", GetAID().Name().c_str(), msgName.c_str());
|
||||
BUS_EXIT("msgName conflicts.");
|
||||
return;
|
||||
}
|
||||
|
||||
appBehaviors.emplace(msgName, behavior);
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
static void BehaviorBase(T *t, void (T::*method)(const AID &, std::unique_ptr<M>), std::unique_ptr<MessageBase> msg) {
|
||||
(t->*method)(msg->From(), std::move(std::unique_ptr<M>((M *)static_cast<MessageLocal *>(msg.get())->ptr)));
|
||||
return;
|
||||
}
|
||||
|
||||
protected:
|
||||
// KLOCALMsg handler
|
||||
virtual void HandleLocalMsg(std::unique_ptr<MessageBase> msg) {
|
||||
auto it = appBehaviors.find(msg->Name());
|
||||
if (it != appBehaviors.end()) {
|
||||
it->second(std::move(msg));
|
||||
} else {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "ACTOR can not finds handler:%s",
|
||||
"a=%s,msg=%s,hdlno=%zd", GetAID().Name().c_str(), msg->Name().c_str(), appBehaviors.size());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, APPBehavior> appBehaviors;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_AID_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_AID_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "actor/buslog.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
constexpr auto BUS_TCP = "tcp";
|
||||
constexpr auto BUS_UDP = "udp";
|
||||
|
||||
class AID {
|
||||
public:
|
||||
AID() : name(), url() {}
|
||||
|
||||
~AID() {}
|
||||
|
||||
AID(const char *name);
|
||||
AID(const std::string &name);
|
||||
|
||||
AID(const std::string &tmpName, const std::string &sUrl) : name(tmpName), url(sUrl) { SetUnfixUrl(); }
|
||||
|
||||
AID(const AID &id) : name(id.name), url(id.url) { SetUnfixUrl(); }
|
||||
|
||||
// Overloading of Assignment Operator
|
||||
AID &operator=(const AID &id);
|
||||
|
||||
inline void SetUrl(const std::string &tmpUrl) {
|
||||
url = tmpUrl;
|
||||
SetUnfixUrl();
|
||||
}
|
||||
|
||||
inline void SetName(const std::string &tmpName) { name = tmpName; }
|
||||
|
||||
inline const std::string &Name() const { return name; }
|
||||
|
||||
inline const std::string &Url() const { return url; }
|
||||
|
||||
void SetProtocol(const std::string &protocol);
|
||||
bool OK() const;
|
||||
|
||||
std::string GetProtocol() const;
|
||||
std::string GetIp() const;
|
||||
uint16_t GetPort() const;
|
||||
inline std::string UnfixUrl() const { return GetIp() + ":" + std::to_string(GetPort()); }
|
||||
inline operator std::string() const { return name + "@" + url; }
|
||||
|
||||
inline std::string HashString() const { return name + "@" + UnfixUrl(); }
|
||||
|
||||
private:
|
||||
void SetUnfixUrl();
|
||||
|
||||
friend class Actor;
|
||||
|
||||
// actor's name
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
tcp://ip:port
|
||||
udp://ip:port
|
||||
ip:port (tcp)
|
||||
**/
|
||||
std::string url;
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const AID &aid) {
|
||||
os << aid.Name() << "@" << aid.Url();
|
||||
return os;
|
||||
}
|
||||
|
||||
inline bool operator==(const AID &aid1, const AID &aid2) {
|
||||
if (aid1.GetProtocol() == BUS_TCP && aid2.GetProtocol() == BUS_TCP) {
|
||||
// NOTE : By default, http has no protocol filed, so we use 'UnfixUrl' to compare aids here
|
||||
return ((aid1.Name() == aid2.Name()) && (aid1.UnfixUrl() == aid2.UnfixUrl()));
|
||||
} else {
|
||||
return ((aid1.Name() == aid2.Name()) && (aid1.Url() == aid2.Url()));
|
||||
}
|
||||
}
|
||||
inline bool operator!=(const AID &aid1, const AID &aid2) { return !(aid1 == aid2); }
|
||||
|
||||
inline bool operator>(const AID &aid1, const AID &aid2) { return aid1.HashString() > aid2.HashString(); }
|
||||
inline bool operator<(const AID &aid1, const AID &aid2) { return aid1.HashString() < aid2.HashString(); }
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
// custom specialization of std::hash can be injected in namespace std
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<mindspore::AID> {
|
||||
typedef mindspore::AID argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const &s) const noexcept { return (std::hash<std::string>{}(s.HashString())); }
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_BUSERRCODE_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_BUSERRCODE_H
|
||||
|
||||
// common err code -1 ~ -100
|
||||
constexpr int BUS_ERROR = -1;
|
||||
constexpr int BUS_OK = 0;
|
||||
constexpr int COMM_NULL_PTR = -1;
|
||||
constexpr int ERRORCODE_SUCCESS = 1;
|
||||
|
||||
// actor module err code -101 ~ -200
|
||||
constexpr int ACTOR_PARAMER_ERR = -101;
|
||||
constexpr int ACTOR_NOT_FIND = -102;
|
||||
constexpr int IO_NOT_FIND = -103;
|
||||
|
||||
// TCP module err code -301 ~ -400
|
||||
// Null
|
||||
// UDP IO err code -401 ~ -500
|
||||
constexpr int UDP_MSG_TOO_BIG = -401;
|
||||
constexpr int UDP_MSG_WRITE_ERR = -402;
|
||||
constexpr int UDP_MSG_SEND_ERR = -403;
|
||||
constexpr int UDP_MSG_ADDR_ERR = -404;
|
||||
constexpr int UDP_MSG_SEND_SUCCESS = 1;
|
||||
|
||||
// Protocol module err code -501 ~ -600
|
||||
constexpr int PB_MSG_NO_NAME = -501;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_BUSLOG_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_BUSLOG_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include "actor/buserrcode.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
#define BUS_LOG(severity) // LOG(severity)
|
||||
#define BUS_DLOG(verboselevel) // VLOG(verboselevel)
|
||||
|
||||
#define HARES_LOG_PID int // GetLogPID();
|
||||
#define PID_LITEBUS_LOG
|
||||
|
||||
#define ICTSBASE_LOG_COMMON_CODE
|
||||
#define HLOG_LEVEL_INFO
|
||||
#define PID_LITEBUS_LOG
|
||||
//#define BUS_OOM_EXIT
|
||||
#define HLOG_LEVEL_DEBUG 1
|
||||
#define ICTSBASE_LOG0(logig, level, pid, format)
|
||||
#define ICTSBASE_LOG1(logig, level, pid, format, para)
|
||||
#define ICTSBASE_LOG2(logig, level, pid, format, para1, para2)
|
||||
#define ICTSBASE_LOG3(logig, level, pid, format, para1, para2, para3)
|
||||
#define ICTSBASE_LOG4(logig, level, pid, format, para1, para2, para3, para4)
|
||||
#define ICTSBASE_LOG_STRING(logig, level, pid, preformat, format...)
|
||||
#define FlushHLogCache()
|
||||
// Kill the process for safe exiting.
|
||||
inline void KillProcess(const std::string &ret) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "BUS Exit Tip: %s", "%s",
|
||||
ret.c_str());
|
||||
// flush the log in cache to disk before exiting.
|
||||
FlushHLogCache();
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
constexpr int DLEVEL4 = 1000;
|
||||
constexpr int DLEVEL3 = 3;
|
||||
constexpr int DLEVEL2 = 2;
|
||||
constexpr int DLEVEL1 = 1;
|
||||
constexpr int DLEVEL0 = 0;
|
||||
|
||||
#define BUS_ASSERT(expression) \
|
||||
do { \
|
||||
if (!(expression)) { \
|
||||
std::stringstream ss; \
|
||||
ss << "Assertion failed: " << #expression << ", file: " << __FILE__ << ", line: " << __LINE__; \
|
||||
mindspore::KillProcess(ss.str()); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUS_EXIT(ret) \
|
||||
do { \
|
||||
std::stringstream ss; \
|
||||
ss << (ret) << " ( file: " << __FILE__ << ", line: " << __LINE__ << " )."; \
|
||||
mindspore::KillProcess(ss.str()); \
|
||||
} while (0)
|
||||
|
||||
#define BUS_OOM_EXIT(ptr) \
|
||||
{ \
|
||||
if (ptr == nullptr) { \
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "new failed, will exit"); \
|
||||
BUS_EXIT("Exit for OOM."); \
|
||||
} \
|
||||
}
|
||||
|
||||
constexpr int LOG_CHECK_EVERY_FIRSTNUM = 10;
|
||||
constexpr int LOG_CHECK_EVERY_NUM1 = 10;
|
||||
constexpr int LOG_CHECK_EVERY_NUM2 = 100;
|
||||
constexpr int LOG_CHECK_EVERY_NUM3 = 1000;
|
||||
constexpr int LOG_CHECK_EVERY_NUM4 = 10000;
|
||||
|
||||
#define LOG_CHECK_ID_CONCAT(word1, word2) word1##word2
|
||||
|
||||
#define LOG_CHECK_ID LOG_CHECK_ID_CONCAT(__FUNCTION__, __LINE__)
|
||||
|
||||
#define LOG_CHECK_FIRST_N \
|
||||
[](uint32_t firstNum) { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return (LOG_CHECK_ID <= firstNum); \
|
||||
}
|
||||
|
||||
#define LOG_CHECK_EVERY_N1 \
|
||||
[](uint32_t firstNum, uint32_t num) { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return ((LOG_CHECK_ID <= firstNum) || (LOG_CHECK_ID % num == 0)); \
|
||||
}
|
||||
|
||||
#define LOG_CHECK_EVERY_N2 \
|
||||
[](uint32_t firstNum, uint32_t num1, uint32_t num2) { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return ((LOG_CHECK_ID <= firstNum) || (LOG_CHECK_ID < num2 && LOG_CHECK_ID % num1 == 0) || \
|
||||
(LOG_CHECK_ID % num2 == 0)); \
|
||||
}
|
||||
|
||||
#define LOG_CHECK_EVERY_N3 \
|
||||
[](uint32_t firstNum, uint32_t num1, uint32_t num2, uint32_t num3) { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return ((LOG_CHECK_ID <= firstNum) || (LOG_CHECK_ID < num2 && LOG_CHECK_ID % num1 == 0) || \
|
||||
(LOG_CHECK_ID < num3 && LOG_CHECK_ID % num2 == 0) || (LOG_CHECK_ID % num3 == 0)); \
|
||||
}
|
||||
|
||||
#define LOG_CHECK_EVERY_N4 \
|
||||
[](uint32_t firstNum, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4) { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return ((LOG_CHECK_ID <= firstNum) || (LOG_CHECK_ID < num2 && LOG_CHECK_ID % num1 == 0) || \
|
||||
(LOG_CHECK_ID < num3 && LOG_CHECK_ID % num2 == 0) || (LOG_CHECK_ID < num4 && LOG_CHECK_ID % num3 == 0) || \
|
||||
(LOG_CHECK_ID % num4 == 0)); \
|
||||
}
|
||||
|
||||
#define LOG_CHECK_EVERY_N \
|
||||
[]() { \
|
||||
static uint32_t LOG_CHECK_ID = 0; \
|
||||
++LOG_CHECK_ID; \
|
||||
return ((LOG_CHECK_ID <= LOG_CHECK_EVERY_FIRSTNUM) || \
|
||||
(LOG_CHECK_ID < LOG_CHECK_EVERY_NUM2 && LOG_CHECK_ID % LOG_CHECK_EVERY_NUM1 == 0) || \
|
||||
(LOG_CHECK_ID < LOG_CHECK_EVERY_NUM3 && LOG_CHECK_ID % LOG_CHECK_EVERY_NUM2 == 0) || \
|
||||
(LOG_CHECK_ID < LOG_CHECK_EVERY_NUM4 && LOG_CHECK_ID % LOG_CHECK_EVERY_NUM3 == 0) || \
|
||||
(LOG_CHECK_ID % LOG_CHECK_EVERY_NUM4 == 0)); \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_MSG_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_MSG_H
|
||||
|
||||
#include "actor/aid.h"
|
||||
|
||||
namespace mindspore {
|
||||
class ActorBase;
|
||||
class MessageBase {
|
||||
public:
|
||||
enum class Type : char {
|
||||
KMSG = 1,
|
||||
KUDP,
|
||||
KHTTP,
|
||||
KASYNC,
|
||||
KLOCAL,
|
||||
KEXIT,
|
||||
KTERMINATE,
|
||||
};
|
||||
|
||||
MessageBase(Type eType = Type::KMSG) : from(), name(), type(eType) {}
|
||||
|
||||
explicit MessageBase(const std::string &sName, Type eType = Type::KMSG) : from(), name(sName), type(eType) {}
|
||||
|
||||
explicit MessageBase(const AID &aFrom, const AID &aTo, Type eType = Type::KMSG)
|
||||
: from(aFrom), to(aTo), name(), body(), type(eType) {}
|
||||
|
||||
explicit MessageBase(const AID &aFrom, const AID &aTo, const std::string &sName, Type eType = Type::KMSG)
|
||||
: from(aFrom), to(aTo), name(sName), body(), type(eType) {}
|
||||
|
||||
explicit MessageBase(const AID &aFrom, const AID &aTo, const std::string &sName, std::string &&sBody,
|
||||
Type eType = Type::KMSG)
|
||||
: from(aFrom), to(aTo), name(sName), body(std::move(sBody)), type(eType) {}
|
||||
|
||||
virtual ~MessageBase() {}
|
||||
|
||||
inline std::string &Name() { return name; }
|
||||
|
||||
inline void SetName(const std::string &aName) { this->name = aName; }
|
||||
|
||||
inline AID &From() { return from; }
|
||||
|
||||
inline std::string &Body() { return body; }
|
||||
|
||||
inline void SetFrom(const AID &aFrom) { from = aFrom; }
|
||||
|
||||
inline AID &To() { return to; }
|
||||
|
||||
inline void SetTo(const AID &aTo) { to = aTo; }
|
||||
|
||||
inline const Type GetType() const { return type; }
|
||||
|
||||
inline void SetType(Type eType) { type = eType; }
|
||||
|
||||
virtual void Run(ActorBase *actor) {}
|
||||
|
||||
friend class ActorBase;
|
||||
friend class TCPMgr;
|
||||
AID from;
|
||||
AID to;
|
||||
std::string name;
|
||||
std::string body;
|
||||
Type type;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // __LITEBUS_MESSAGE_HPP__
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_NAUGHT_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ACTOR_NAUGHT_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class Naught;
|
||||
class ActorBase;
|
||||
|
||||
typedef std::shared_ptr<Naught> UniqueNaught;
|
||||
typedef std::shared_ptr<Naught> SharedNaught;
|
||||
typedef std::string BusString;
|
||||
|
||||
// Lite , start from Naught
|
||||
class Naught {
|
||||
public:
|
||||
virtual ~Naught() {}
|
||||
};
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_APPLY_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_APPLY_H
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T, T... Ints>
|
||||
struct IntegerSequenceBase {
|
||||
static constexpr std::size_t Size() noexcept { return sizeof...(Ints); }
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename T, std::size_t N, std::size_t... Ints>
|
||||
struct IntegerSequence : public IntegerSequence<T, N - 1, N - 1, Ints...> {};
|
||||
|
||||
template <typename T, std::size_t... Ints>
|
||||
struct IntegerSequence<T, 0, Ints...> {
|
||||
using type = IntegerSequenceBase<T, Ints...>;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
using make_integer_sequence = typename internal::IntegerSequence<T, N>::type;
|
||||
|
||||
template <std::size_t... Ints>
|
||||
using index_sequence = IntegerSequenceBase<std::size_t, Ints...>;
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
|
||||
template <class... T>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(T)>;
|
||||
|
||||
template <typename Func, typename Tuple, std::size_t... Ints>
|
||||
auto ApplyHelper(Func &&func, Tuple &&tuple, index_sequence<Ints...>)
|
||||
-> decltype(func(std::get<Ints>(std::forward<Tuple>(tuple))...)) {
|
||||
return func(std::get<Ints>(std::forward<Tuple>(tuple))...);
|
||||
}
|
||||
|
||||
template <typename T, typename Func, typename Tuple, std::size_t... Ints>
|
||||
auto ApplyHelper(T *ptr, Func &&func, Tuple &&tuple, index_sequence<Ints...>)
|
||||
-> decltype((ptr->*func)(std::get<Ints>(std::forward<Tuple>(tuple))...)) {
|
||||
return (ptr->*func)(std::get<Ints>(std::forward<Tuple>(tuple))...);
|
||||
}
|
||||
|
||||
template <typename Func, typename Tuple>
|
||||
auto Apply(Func &&func, Tuple &&tuple)
|
||||
-> decltype(ApplyHelper(std::forward<Func>(func), std::forward<Tuple>(tuple),
|
||||
make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{})) {
|
||||
return ApplyHelper(std::forward<Func>(func), std::forward<Tuple>(tuple),
|
||||
make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{});
|
||||
}
|
||||
|
||||
template <typename T, typename Func, typename Tuple>
|
||||
auto Apply(T *ptr, Func &&func, Tuple &&tuple)
|
||||
-> decltype(ApplyHelper(ptr, std::forward<Func>(func), std::forward<Tuple>(tuple),
|
||||
make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{})) {
|
||||
return ApplyHelper(ptr, std::forward<Func>(func), std::forward<Tuple>(tuple),
|
||||
make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{});
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,271 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_ASYNC_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_ASYNC_H
|
||||
|
||||
#include "actor/actor.h"
|
||||
#include "actor/buslog.h"
|
||||
|
||||
#include "async/apply.h"
|
||||
#include "async/future.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
using MessageHandler = std::function<void(ActorBase *)>;
|
||||
|
||||
void Async(const AID &aid, std::unique_ptr<MessageHandler> handler);
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename R>
|
||||
struct AsyncHelper;
|
||||
|
||||
// for defer
|
||||
template <>
|
||||
struct AsyncHelper<void> {
|
||||
template <typename F>
|
||||
void operator()(const AID &aid, F &&f) {
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([=](ActorBase *) { f(); }));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct AsyncHelper<Future<R>> {
|
||||
template <typename F>
|
||||
Future<R> operator()(const AID &aid, F &&f) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([=](ActorBase *) { promise->Associate(f()); }));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct AsyncHelper {
|
||||
template <typename F>
|
||||
Future<R> operator()(const AID &aid, F &&f) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([=](ActorBase *) { promise->SetValue(f()); }));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// return void
|
||||
template <typename T>
|
||||
void Async(const AID &aid, void (T::*method)()) {
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([method](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
(t->*method)();
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
}
|
||||
|
||||
template <typename T, typename Arg0, typename Arg1>
|
||||
void Async(const AID &aid, void (T::*method)(Arg0), Arg1 &&arg) {
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([method, arg](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
(t->*method)(arg);
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
void Async(const AID &aid, void (T::*method)(Args0...), std::tuple<Args1...> &&tuple) {
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([method, tuple](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
Apply(t, method, tuple);
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
Async(aid, std::move(handler));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
void Async(const AID &aid, void (T::*method)(Args0...), Args1 &&... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args1>(args)...);
|
||||
Async(aid, method, std::move(tuple));
|
||||
}
|
||||
|
||||
// return future
|
||||
template <typename R, typename T>
|
||||
Future<R> Async(const AID &aid, Future<R> (T::*method)()) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->Associate((t->*method)());
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename T, typename Arg0, typename Arg1>
|
||||
Future<R> Async(const AID &aid, Future<R> (T::*method)(Arg0), Arg1 &&arg) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method, arg](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->Associate((t->*method)(arg));
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename T, typename... Args0, typename... Args1>
|
||||
Future<R> Async(const AID &aid, Future<R> (T::*method)(Args0...), std::tuple<Args1...> &&tuple) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method, tuple](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->Associate(Apply(t, method, tuple));
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename T, typename... Args0, typename... Args1>
|
||||
Future<R> Async(const AID &aid, Future<R> (T::*method)(Args0...), Args1 &&... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args1>(args)...);
|
||||
return Async(aid, method, std::move(tuple));
|
||||
}
|
||||
|
||||
// return R
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
|
||||
typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T>
|
||||
Future<R> Async(const AID &aid, R (T::*method)()) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->SetValue((t->*method)());
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
|
||||
typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename Arg0,
|
||||
typename Arg1>
|
||||
Future<R> Async(const AID &aid, R (T::*method)(Arg0), Arg1 &&arg) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method, arg](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->SetValue((t->*method)(arg));
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
|
||||
typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename... Args0,
|
||||
typename... Args1>
|
||||
Future<R> Async(const AID &aid, R (T::*method)(Args0...), std::tuple<Args1...> &&tuple) {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::unique_ptr<std::function<void(ActorBase *)>> handler(
|
||||
new (std::nothrow) std::function<void(ActorBase *)>([promise, method, tuple](ActorBase *actor) {
|
||||
BUS_ASSERT(actor != nullptr);
|
||||
T *t = static_cast<T *>(actor);
|
||||
BUS_ASSERT(t != nullptr);
|
||||
promise->SetValue(Apply(t, method, tuple));
|
||||
}));
|
||||
BUS_OOM_EXIT(handler);
|
||||
|
||||
Async(aid, std::move(handler));
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
|
||||
typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename... Args0,
|
||||
typename... Args1>
|
||||
Future<R> Async(const AID &aid, R (T::*method)(Args0...), Args1 &&... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args1>(args)...);
|
||||
return Async(aid, method, std::move(tuple));
|
||||
}
|
||||
|
||||
template <typename F, typename R = typename std::result_of<F()>::type>
|
||||
auto Async(const AID &aid, F &&f) -> decltype(internal::AsyncHelper<R>()(aid, std::forward<F>(f))) {
|
||||
return internal::AsyncHelper<R>()(aid, std::forward<F>(f));
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_ASYNCAFTER_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_ASYNCAFTER_H
|
||||
|
||||
#include "async/async.h"
|
||||
|
||||
#include "timer/timertools.h"
|
||||
|
||||
constexpr mindspore::Duration MILLISECONDS = 1;
|
||||
constexpr mindspore::Duration SECONDS = 1000;
|
||||
|
||||
namespace mindspore {
|
||||
template <typename T>
|
||||
Timer AsyncAfter(const Duration &duration, const AID &aid, void (T::*method)()) {
|
||||
return TimerTools::AddTimer(duration, aid, [=]() { Async(aid, method); });
|
||||
}
|
||||
|
||||
template <typename T, typename Arg0, typename Arg1>
|
||||
Timer AsyncAfter(const Duration &duration, const AID &aid, void (T::*method)(Arg0), Arg1 &&arg) {
|
||||
return TimerTools::AddTimer(duration, aid, [=]() { Async(aid, method, arg); });
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
Timer AsyncAfter(const Duration &duration, const AID &aid, void (T::*method)(Args0...), Args1 &&... args) {
|
||||
std::function<void(Args0...)> f([=](Args0... args0) { Async(aid, method, args0...); });
|
||||
|
||||
auto handler = std::bind(f, args...);
|
||||
|
||||
return TimerTools::AddTimer(duration, aid, [=]() { Async(aid, std::move(handler)); });
|
||||
}
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_COLLECT_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_COLLECT_H
|
||||
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "async/common.h"
|
||||
#include "async/future.h"
|
||||
#include "async/spinlock.h"
|
||||
|
||||
#include "actor/actor.h"
|
||||
|
||||
#include "litebus.hpp"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T>
|
||||
class Future;
|
||||
|
||||
template <typename T>
|
||||
class Promise;
|
||||
|
||||
template <typename T>
|
||||
class Collected;
|
||||
|
||||
template <typename T>
|
||||
class Collected {
|
||||
public:
|
||||
Collected(const std::list<Future<T>> &f, Promise<std::list<T>> *p) : futures(f), promise(p), ready(0) {}
|
||||
|
||||
virtual ~Collected() {
|
||||
delete promise;
|
||||
promise = nullptr;
|
||||
}
|
||||
|
||||
Collected(const Collected &) = delete;
|
||||
Collected(Collected &&) = default;
|
||||
|
||||
Collected &operator=(const Collected &) = delete;
|
||||
Collected &operator=(Collected &&) = default;
|
||||
|
||||
public:
|
||||
void Discarded() {
|
||||
auto iter = futures.begin();
|
||||
for (; iter != futures.end(); ++iter) {
|
||||
iter->SetFailed(Status::KERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void Waited(const Future<T> &future) {
|
||||
if (future.IsError()) {
|
||||
promise->SetFailed(future.GetErrorCode());
|
||||
} else if (future.IsOK()) {
|
||||
ready.fetch_add(1);
|
||||
if (ready.load() == futures.size()) {
|
||||
std::list<T> values;
|
||||
auto iter = futures.begin();
|
||||
for (; iter != futures.end(); ++iter) {
|
||||
values.push_back(iter->Get());
|
||||
}
|
||||
promise->SetValue(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::list<Future<T>> futures;
|
||||
Promise<std::list<T>> *promise;
|
||||
std::atomic_ulong ready;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Future<std::list<T>> Collect(const std::list<Future<T>> &futures) {
|
||||
if (futures.empty()) {
|
||||
return std::list<T>();
|
||||
}
|
||||
|
||||
Promise<std::list<T>> *promise = new (std::nothrow) Promise<std::list<T>>();
|
||||
BUS_OOM_EXIT(promise);
|
||||
using CollectType = Collected<T>;
|
||||
std::shared_ptr<CollectType> collect = std::make_shared<CollectType>(futures, promise);
|
||||
|
||||
//
|
||||
auto iter = futures.begin();
|
||||
for (; iter != futures.end(); ++iter) {
|
||||
iter->OnComplete(Defer(collect, &CollectType::Waited, std::placeholders::_1));
|
||||
}
|
||||
|
||||
Future<std::list<T>> future = promise->GetFuture();
|
||||
future.OnComplete(Defer(collect, &Collected<T>::Discarded));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
Future<std::tuple<Ts...>> Collect(const Future<Ts> &... futures) {
|
||||
std::list<Future<Nothing>> wrappers = {futures.Then([]() { return Nothing(); })...};
|
||||
|
||||
auto f = [](const Future<Ts> &... futures) { return std::make_tuple(futures.Get()...); };
|
||||
|
||||
return Collect(wrappers).Then(std::bind(f, futures...));
|
||||
}
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_COMMON_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_COMMON_H
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
struct Nothing {};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif /* COMMON_HPP__ */
|
|
@ -0,0 +1,316 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_DEFER_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_DEFER_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "async/async.h"
|
||||
#include "async/option.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename F>
|
||||
class Deferred : public std::function<F> {
|
||||
public:
|
||||
virtual ~Deferred() {}
|
||||
|
||||
private:
|
||||
template <typename G>
|
||||
friend class internal::DeferredHelper;
|
||||
|
||||
template <typename T>
|
||||
friend Deferred<void()> Defer(const AID &aid, void (T::*method)());
|
||||
|
||||
template <typename R, typename T>
|
||||
friend Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)());
|
||||
|
||||
template <typename R, typename T>
|
||||
friend Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)());
|
||||
|
||||
Deferred(const std::function<F> &f) : std::function<F>(f) {}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename F>
|
||||
class DeferredHelper {
|
||||
public:
|
||||
DeferredHelper(const AID &id, F &&function) : aid(id), f(std::forward<F>(function)) {}
|
||||
|
||||
DeferredHelper(F &&function) : f(std::forward<F>(function)) {}
|
||||
|
||||
~DeferredHelper() {}
|
||||
|
||||
operator Deferred<void()>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void()>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void()>([=]() { Async(optionAid.Get(), function); });
|
||||
}
|
||||
|
||||
operator std::function<void()>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void()>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void()>([=]() { Async(optionAid.Get(), function); });
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
operator Deferred<R()>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R()>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
operator std::function<R()>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R()>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
operator Deferred<void(Arg)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void(Arg)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void(Arg)>([=](Arg arg) {
|
||||
std::function<void()> handler([=]() { function(arg); });
|
||||
Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
operator std::function<void(Arg)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void(Arg)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void(Arg)>([=](Arg arg) {
|
||||
std::function<void()> handler([=]() { function(arg); });
|
||||
Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
operator Deferred<void(Args...)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void(Args...)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void(Args...)>([=](Args... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args>(args)...);
|
||||
std::function<void()> handler([=]() { Apply(function, tuple); });
|
||||
Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
operator std::function<void(Args...)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<void(Args...)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<void(Args...)>([=](Args... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args>(args)...);
|
||||
std::function<void()> handler([=]() { Apply(function, tuple); });
|
||||
Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
|
||||
operator Deferred<R(Arg)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R(Arg)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R(Arg)>([=](Arg arg) {
|
||||
std::function<R()> handler([=]() { return function(arg); });
|
||||
return Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
|
||||
operator std::function<R(Arg)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R(Arg)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R(Arg)>([=](Arg arg) {
|
||||
std::function<R()> handler([=]() { return function(arg); });
|
||||
return Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
|
||||
operator Deferred<R(Args...)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R(Args...)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R(Args...)>([=](Args... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args>(args)...);
|
||||
std::function<R()> handler([=]() { return Apply(function, tuple); });
|
||||
return Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
|
||||
operator std::function<R(Args...)>() && {
|
||||
if (aid.IsNone()) {
|
||||
return std::function<R(Args...)>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
Option<AID> optionAid = aid;
|
||||
F &&function = std::forward<F>(f);
|
||||
|
||||
return std::function<R(Args...)>([=](Args... args) {
|
||||
auto tuple = std::make_tuple(std::forward<Args>(args)...);
|
||||
std::function<R()> handler([=]() { return Apply(function, tuple); });
|
||||
return Async(optionAid.Get(), handler);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename G>
|
||||
friend DeferredHelper<G> Defer(const AID &aid, G &&g);
|
||||
|
||||
Option<AID> aid;
|
||||
F f;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename F>
|
||||
internal::DeferredHelper<F> Defer(const AID &aid, F &&f) {
|
||||
return internal::DeferredHelper<F>(aid, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Deferred<void()> Defer(const AID &aid, void (T::*method)()) {
|
||||
return Deferred<void()>([=]() { Async(aid, method); });
|
||||
}
|
||||
|
||||
template <typename R, typename T>
|
||||
Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)()) {
|
||||
return Deferred<Future<R>()>([=]() { return Async(aid, method); });
|
||||
}
|
||||
|
||||
template <typename R, typename T>
|
||||
Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)()) {
|
||||
return Deferred<Future<R>()>([=]() { return Async(aid, method); });
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
auto Defer(T *t, void (T::*method)(Args0...), Args1 &&... args)
|
||||
-> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
|
||||
std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
|
||||
std::function<void(Args0...)> f([=](Args0... args0) {
|
||||
if (t != nullptr) {
|
||||
(t->*method)(args0...);
|
||||
}
|
||||
});
|
||||
|
||||
return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
auto Defer(std::shared_ptr<T> t, void (T::*method)(Args0...), Args1 &&... args)
|
||||
-> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
|
||||
std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
|
||||
std::function<void(Args0...)> f([=](Args0... args0) {
|
||||
if (t != nullptr) {
|
||||
(t.get()->*method)(args0...);
|
||||
}
|
||||
});
|
||||
|
||||
return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args0, typename... Args1>
|
||||
auto Defer(const AID &aid, void (T::*method)(Args0...), Args1 &&... args)
|
||||
-> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
|
||||
std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
|
||||
std::function<void(Args0...)> f([=](Args0... args0) { Async(aid, method, args0...); });
|
||||
|
||||
return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename T, typename... Args0, typename... Args1>
|
||||
auto Defer(const AID &aid, Future<R> (T::*method)(Args0...), Args1 &&... args)
|
||||
-> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
|
||||
std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
|
||||
std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
|
||||
|
||||
return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
|
||||
}
|
||||
|
||||
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
|
||||
typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename... Args0,
|
||||
typename... Args1>
|
||||
auto Defer(const AID &aid, R (T::*method)(Args0...), Args1 &&... args)
|
||||
-> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
|
||||
std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
|
||||
std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
|
||||
|
||||
return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FAILURE_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FAILURE_H
|
||||
|
||||
#include "async/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class Failure : public Status {
|
||||
public:
|
||||
Failure() : Status(Status::KOK), errorCode(Status::KOK) {}
|
||||
|
||||
Failure(int32_t code) : Status(code), errorCode(code) {}
|
||||
|
||||
~Failure() {}
|
||||
|
||||
const int32_t GetErrorCode() const { return errorCode; }
|
||||
|
||||
private:
|
||||
Status::Code errorCode;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif /* __FAILURE_HPP__ */
|
|
@ -0,0 +1,511 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FUTURE_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FUTURE_H
|
||||
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "actor/actor.h"
|
||||
#include "actor/buslog.h"
|
||||
|
||||
#include "async/spinlock.h"
|
||||
#include "async/status.h"
|
||||
#include "async/uuid_generator.h"
|
||||
|
||||
#include "litebus.hpp"
|
||||
|
||||
#include "future_base.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T>
|
||||
class Promise;
|
||||
|
||||
template <typename T>
|
||||
class Option;
|
||||
|
||||
template <typename T>
|
||||
class Future : public FutureBase {
|
||||
public:
|
||||
typedef Status WaitForStatus;
|
||||
typedef typename FutureData<T>::CompleteCallback CompleteCallback;
|
||||
typedef typename FutureData<T>::AbandonedCallback AbandonedCallback;
|
||||
typedef FutureData<T> Data;
|
||||
Future() : data(new (std::nothrow) Data()) {
|
||||
BUS_OOM_EXIT(data);
|
||||
data->abandoned = true;
|
||||
}
|
||||
|
||||
Future(const Future<T> &f) : FutureBase(f), data(f.data) {}
|
||||
|
||||
Future(Future<T> &&f) : data(std::move(f.data)) {}
|
||||
|
||||
Future(const T &t) : data(new (std::nothrow) Data()) {
|
||||
BUS_OOM_EXIT(data);
|
||||
SetValue(std::move(t));
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
Future(const V &value) : data(new (std::nothrow) Data()) {
|
||||
BUS_OOM_EXIT(data);
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
Future(const Status &s) : data(new (std::nothrow) Data()) {
|
||||
BUS_OOM_EXIT(data);
|
||||
SetFailed(s.GetCode());
|
||||
}
|
||||
|
||||
~Future() override {}
|
||||
|
||||
Future<T> &operator=(const Future<T> &f) {
|
||||
if (&f != this) {
|
||||
data = f.data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Future<T> &f) const { return data == f.data; }
|
||||
|
||||
bool operator!=(const Future<T> &f) const { return !(*this == f); }
|
||||
|
||||
const T &Get() const {
|
||||
if (data->status.IsError()) {
|
||||
ICTSBASE_LOG1(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_WARNING, PID_LITEBUS_LOG,
|
||||
"Future::Get() but status == Error: %d", GetErrorCode());
|
||||
return data->t;
|
||||
}
|
||||
|
||||
if (data->gotten) {
|
||||
return data->t;
|
||||
}
|
||||
|
||||
// try {
|
||||
data->t = data->future.get();
|
||||
data->gotten = true;
|
||||
// } catch (std::future_error const &e) {
|
||||
// ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Future error: %s",
|
||||
// "%s",
|
||||
// e.what());
|
||||
// } catch (std::exception const &e) {
|
||||
// ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Standard exception:
|
||||
// %s",
|
||||
// "%s", e.what());
|
||||
// } catch (...) {
|
||||
// ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Unknown exception.");
|
||||
// }
|
||||
|
||||
return data->t;
|
||||
}
|
||||
|
||||
Option<T> Get(uint64_t timeMs) const {
|
||||
if (data->gotten) {
|
||||
return Option<T>(data->t);
|
||||
}
|
||||
|
||||
if (WaitFor(timeMs).IsError()) {
|
||||
return Option<T>();
|
||||
}
|
||||
|
||||
if (data->status.IsError()) {
|
||||
return Option<T>();
|
||||
}
|
||||
|
||||
return Option<T>(Get());
|
||||
}
|
||||
|
||||
bool Valid() const noexcept { return data->future.valid(); }
|
||||
|
||||
bool IsInit() const { return data->status.IsInit(); }
|
||||
|
||||
bool IsOK() const { return data->status.IsOK(); }
|
||||
|
||||
bool IsError() const { return data->status.IsError(); }
|
||||
|
||||
Status GetStatus() const { return data->status; }
|
||||
|
||||
int32_t GetErrorCode() const {
|
||||
const Status &status_ = data->status;
|
||||
if (status_.IsError()) {
|
||||
return status_.GetCode();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Wait() const {
|
||||
if (!data->status.IsInit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
data->future.wait();
|
||||
}
|
||||
|
||||
WaitForStatus WaitFor(uint64_t timeMs) const {
|
||||
if (!data->status.IsInit()) {
|
||||
return Status::KOK;
|
||||
}
|
||||
|
||||
AID aid = mindspore::Spawn(std::make_shared<internal::WaitActor>(
|
||||
internal::WAIT_ACTOR_NAME + std::to_string(mindspore::localid_generator::GenLocalActorId())));
|
||||
|
||||
mindspore::Timer timer = TimerTools::AddTimer(timeMs, aid, std::bind(&internal::Waitf, aid));
|
||||
|
||||
OnComplete(std::bind(&internal::Wait, aid, timer));
|
||||
|
||||
// block
|
||||
mindspore::Await(aid);
|
||||
|
||||
data->lock.Lock();
|
||||
bool ret = data->status.IsInit();
|
||||
data->lock.Unlock();
|
||||
|
||||
if (!ret) {
|
||||
return Status::KOK;
|
||||
}
|
||||
|
||||
return Status::KERROR;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
const Future<T> &OnComplete(internal::DeferredHelper<F> &&deferred) const {
|
||||
return OnComplete(std::move(deferred).operator std::function<void(const Future<T> &)>());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
const Future<T> &OnAbandoned(internal::DeferredHelper<F> &&deferred) const {
|
||||
return OnAbandoned(std::move(deferred).operator std::function<void(const Future<T> &)>());
|
||||
}
|
||||
|
||||
const Future<T> &OnComplete(CompleteCallback &&callback) const {
|
||||
bool call = false;
|
||||
|
||||
data->lock.Lock();
|
||||
if (data->status.IsInit()) {
|
||||
// using move to make callback execute once
|
||||
data->onCompleteCallbacks.push_back(std::move(callback));
|
||||
} else {
|
||||
call = true;
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
std::move(callback)(*this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Future<T> &OnAbandoned(AbandonedCallback &&callback) const {
|
||||
bool call = false;
|
||||
|
||||
data->lock.Lock();
|
||||
if (data->abandoned) {
|
||||
call = true;
|
||||
} else if (data->status.IsInit()) {
|
||||
// using move to make callback execute once
|
||||
data->onAbandonedCallbacks.push_back(std::move(callback));
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
std::move(callback)(*this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SetValue(T &&t) const { return Set(std::move(t)); }
|
||||
|
||||
void SetValue(const T &t) const { return Set(t); }
|
||||
|
||||
void SetOK() const {
|
||||
bool call = false;
|
||||
|
||||
data->lock.Lock();
|
||||
if (data->status.IsInit()) {
|
||||
data->status.SetOK();
|
||||
data->promise.set_value(T());
|
||||
call = true;
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
RunCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
void SetFailed(int32_t errCode) const {
|
||||
BUS_ASSERT(errCode != Status::KINIT && errCode != Status::KOK);
|
||||
|
||||
bool call = false;
|
||||
|
||||
data->lock.Lock();
|
||||
if (data->status.IsInit()) {
|
||||
data->status.SetCode(errCode);
|
||||
data->promise.set_value(T());
|
||||
call = true;
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
RunCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
// remove all callbacks
|
||||
void Clear() const { data->Clear(); }
|
||||
|
||||
void Abandon(bool abandon = false) const {
|
||||
bool call = false;
|
||||
|
||||
std::list<AbandonedCallback> callbacks;
|
||||
data->lock.Lock();
|
||||
if (!data->abandoned && data->status.IsInit() && (!data->associated || abandon)) {
|
||||
call = data->abandoned = true;
|
||||
callbacks.swap(data->onAbandonedCallbacks);
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
internal::Run(std::move(callbacks), *this);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
Future<R> Then(const std::function<Future<R>(const T &)> &f) const {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::function<void(const Future<T> &)> handler =
|
||||
std::bind(&internal::Thenf<T, R>, f, promise, std::placeholders::_1);
|
||||
|
||||
OnComplete(std::move(handler));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
Future<R> Then(const std::function<R(const T &)> &f) const {
|
||||
std::shared_ptr<Promise<R>> promise(new (std::nothrow) Promise<R>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<R> future = promise->GetFuture();
|
||||
|
||||
std::function<void(const Future<T> &)> handler =
|
||||
std::bind(&internal::Then<T, R>, f, promise, std::placeholders::_1);
|
||||
|
||||
OnComplete(std::move(handler));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
Future<R> Then(const std::function<Future<R>()> &f) const {
|
||||
return Then(std::function<Future<R>(const T &)>(std::bind(f)));
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
Future<R> Then(const std::function<R()> &f) const {
|
||||
return Then(std::function<R(const T &)>(std::bind(f)));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
auto Then(F &&f) const -> decltype(this->Then(std::forward<F>(f), FutureBase())) {
|
||||
return Then(std::forward<F>(f), FutureBase());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
const Future<T> &OnComplete(F &&f) const {
|
||||
return OnComplete(std::forward<F>(f), FutureBase());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
const Future<T> &OnAbandoned(F &&f) const {
|
||||
return OnAbandoned(std::forward<F>(f), FutureBase());
|
||||
}
|
||||
|
||||
Future<T> After(const Duration &timeMs, const std::function<Future<T>(const Future<T> &)> &f) const {
|
||||
std::shared_ptr<Promise<T>> promise(new (std::nothrow) Promise<T>());
|
||||
BUS_OOM_EXIT(promise);
|
||||
Future<T> future = promise->GetFuture();
|
||||
|
||||
mindspore::Timer timer =
|
||||
TimerTools::AddTimer(timeMs, "__After__", std::bind(&internal::Afterf<T>, f, promise, *this));
|
||||
|
||||
OnComplete(std::bind(&internal::After<T>, promise, timer, std::placeholders::_1));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F, typename R = typename internal::Unwrap<typename std::result_of<F(const T &)>::type>::type>
|
||||
Future<R> Then(internal::DeferredHelper<F> &&f, FutureBase) const {
|
||||
return Then<R>(std::move(f).operator std::function<Future<R>(const T &)>());
|
||||
}
|
||||
|
||||
template <typename F, typename R = typename internal::Unwrap<typename std::result_of<typename std::enable_if<
|
||||
!std::is_bind_expression<typename std::decay<F>::type>::value, F>::type()>::type>::type>
|
||||
Future<R> Then(internal::DeferredHelper<F> &&f, LessFuture) const {
|
||||
return Then<R>(std::move(f).operator std::function<Future<R>()>());
|
||||
}
|
||||
|
||||
template <typename F, typename R = typename internal::Unwrap<typename std::result_of<F(const T &)>::type>::type>
|
||||
Future<R> Then(F &&f, FutureBase) const {
|
||||
return Then<R>(std::function<Future<R>(const T &)>(f));
|
||||
}
|
||||
|
||||
template <typename F, typename R = typename internal::Unwrap<typename std::result_of<typename std::enable_if<
|
||||
!std::is_bind_expression<typename std::decay<F>::type>::value, F>::type()>::type>::type>
|
||||
Future<R> Then(F &&f, LessFuture) const {
|
||||
return Then<R>(std::function<Future<R>()>(std::forward<F>(f)));
|
||||
}
|
||||
|
||||
template <typename F, typename = typename std::result_of<F(const Future<T> &)>::type>
|
||||
const Future<T> &OnComplete(F &&f, FutureBase) const {
|
||||
return OnComplete(
|
||||
std::function<void(const Future<T> &)>([=](const Future<T> &future) mutable { std::forward<F>(f)(future); }));
|
||||
}
|
||||
|
||||
template <typename F, typename = typename std::result_of<typename std::enable_if<
|
||||
!std::is_bind_expression<typename std::decay<F>::type>::value, F>::type()>::type>
|
||||
const Future<T> &OnComplete(F &&f, LessFuture) const {
|
||||
return OnComplete(std::function<void(const Future<T> &)>([=](const Future<T> &) mutable { std::forward<F>(f)(); }));
|
||||
}
|
||||
|
||||
template <typename F, typename = typename std::result_of<F(const Future<T> &)>::type>
|
||||
const Future<T> &OnAbandoned(F &&f, FutureBase) const {
|
||||
return OnAbandoned(
|
||||
std::function<void(const Future<T> &)>([=](const Future<T> &future) mutable { std::forward<F>(f)(future); }));
|
||||
}
|
||||
|
||||
template <typename F, typename = typename std::result_of<typename std::enable_if<
|
||||
!std::is_bind_expression<typename std::decay<F>::type>::value, F>::type()>::type>
|
||||
const Future<T> &OnAbandoned(F &&f, LessFuture) const {
|
||||
return OnAbandoned(
|
||||
std::function<void(const Future<T> &)>([=](const Future<T> &) mutable { std::forward<F>(f)(); }));
|
||||
}
|
||||
|
||||
void RunCallbacks() const {
|
||||
std::shared_ptr<typename Future<T>::Data> copy = data;
|
||||
internal::Run(std::move(copy->onCompleteCallbacks), Future<T>(copy));
|
||||
copy->Clear();
|
||||
}
|
||||
|
||||
void Run() const {
|
||||
auto iter = data->onCompleteCallbacks.begin();
|
||||
for (; iter != data->onCompleteCallbacks.end(); ++iter) {
|
||||
(*iter)(*this);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
void Set(V &&value) const {
|
||||
bool call = false;
|
||||
|
||||
data->lock.Lock();
|
||||
if (data->status.IsInit()) {
|
||||
data->status.SetOK();
|
||||
data->promise.set_value(std::forward<V>(value));
|
||||
call = true;
|
||||
}
|
||||
data->lock.Unlock();
|
||||
|
||||
if (call) {
|
||||
RunCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
friend class Future;
|
||||
friend class Promise<T>;
|
||||
|
||||
Future(const std::shared_ptr<Data> &t) : data(t) {}
|
||||
|
||||
std::shared_ptr<Data> data;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Promise {
|
||||
public:
|
||||
Promise() : future() { future.data->abandoned = false; }
|
||||
|
||||
explicit Promise(const T &t) : future(t) {}
|
||||
|
||||
virtual ~Promise() {
|
||||
// try {
|
||||
if (future.data) {
|
||||
future.Abandon();
|
||||
}
|
||||
// } catch (...) {
|
||||
// }
|
||||
}
|
||||
|
||||
void SetValue(const T &value) const { Set(value); }
|
||||
|
||||
void SetValue(T &&value) const { Set(std::move(value)); }
|
||||
|
||||
void SetValue(const Future<T> &tFuture) const { Associate(tFuture); }
|
||||
|
||||
void SetFailed(int32_t code) const {
|
||||
if (!future.data->associated) {
|
||||
future.SetFailed(code);
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> GetFuture() const { return future; }
|
||||
|
||||
void Associate(const Future<T> &f) const {
|
||||
bool associated = false;
|
||||
|
||||
future.data->lock.Lock();
|
||||
if (future.IsInit() && !future.data->associated) {
|
||||
associated = (future.data->associated = true);
|
||||
}
|
||||
future.data->lock.Unlock();
|
||||
|
||||
if (associated) {
|
||||
f.OnComplete(std::bind(&internal::Complete<T>, future, std::placeholders::_1))
|
||||
.OnAbandoned(std::bind(&internal::Abandon<T>, future, true));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename V>
|
||||
void Set(V &&value) const {
|
||||
if (future.IsInit() && !future.data->associated) {
|
||||
future.SetValue(std::forward<V>(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
friend class Future;
|
||||
|
||||
Future<T> future;
|
||||
};
|
||||
|
||||
template <>
|
||||
class Promise<void>;
|
||||
|
||||
template <typename T>
|
||||
class Promise<T &>;
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FUTURE_BASE_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_FUTURE_BASE_H
|
||||
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "actor/actor.h"
|
||||
#include "actor/buslog.h"
|
||||
#include "async/spinlock.h"
|
||||
#include "async/status.h"
|
||||
|
||||
#include "timer/timertools.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T>
|
||||
class Future;
|
||||
|
||||
template <typename T>
|
||||
class Promise;
|
||||
|
||||
class LessFuture {
|
||||
public:
|
||||
LessFuture() {}
|
||||
LessFuture(const LessFuture &obj) {}
|
||||
LessFuture &operator=(const LessFuture &) = delete;
|
||||
virtual ~LessFuture() {}
|
||||
};
|
||||
|
||||
class FutureBase : public LessFuture {
|
||||
public:
|
||||
FutureBase() {}
|
||||
FutureBase(const FutureBase &obj) : LessFuture(obj) {}
|
||||
FutureBase &operator=(const FutureBase &) = delete;
|
||||
~FutureBase() override {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FutureData {
|
||||
public:
|
||||
typedef std::function<void(const Future<T> &)> CompleteCallback;
|
||||
typedef std::function<void(const Future<T> &)> AbandonedCallback;
|
||||
|
||||
FutureData()
|
||||
: status(Status::KINIT),
|
||||
associated(false),
|
||||
abandoned(false),
|
||||
gotten(false),
|
||||
promise(),
|
||||
future(promise.get_future()),
|
||||
t() {}
|
||||
|
||||
~FutureData() {
|
||||
// try {
|
||||
Clear();
|
||||
// } catch (...) {
|
||||
// }
|
||||
}
|
||||
|
||||
// remove all callbacks
|
||||
void Clear() {
|
||||
onCompleteCallbacks.clear();
|
||||
onAbandonedCallbacks.clear();
|
||||
}
|
||||
|
||||
// status of future
|
||||
SpinLock lock;
|
||||
Status status;
|
||||
|
||||
bool associated;
|
||||
bool abandoned;
|
||||
bool gotten;
|
||||
|
||||
std::promise<T> promise;
|
||||
|
||||
// get from promise
|
||||
std::future<T> future;
|
||||
|
||||
// complete callback
|
||||
std::list<CompleteCallback> onCompleteCallbacks;
|
||||
|
||||
// abandoned callback
|
||||
std::list<AbandonedCallback> onAbandonedCallbacks;
|
||||
|
||||
T t;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
const std::string WAIT_ACTOR_NAME = "WACTOR_";
|
||||
|
||||
class WaitActor : public ActorBase {
|
||||
public:
|
||||
explicit WaitActor(const std::string &name) : mindspore::ActorBase(name) {}
|
||||
|
||||
~WaitActor() override {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class DeferredHelper;
|
||||
|
||||
template <typename T>
|
||||
struct Wrap {
|
||||
typedef Future<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Wrap<Future<T>> {
|
||||
typedef Future<T> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Unwrap {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Unwrap<Future<T>> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsFuture : public std::integral_constant<bool, std::is_base_of<FutureBase, T>::value> {};
|
||||
|
||||
template <typename H, typename... Args>
|
||||
static void Run(std::list<H> &&handlers, Args &&... args) {
|
||||
for (auto iter = handlers.begin(); iter != handlers.end(); ++iter) {
|
||||
std::move (*iter)(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void Complete(const Future<T> &future, const Future<T> &f) {
|
||||
if (f.IsError()) {
|
||||
future.SetFailed(f.GetErrorCode());
|
||||
} else if (f.IsOK()) {
|
||||
future.SetValue(f.Get());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void Abandon(const Future<T> &future, bool abandon) {
|
||||
future.Abandon(abandon);
|
||||
}
|
||||
|
||||
template <typename T, typename R>
|
||||
static void Thenf(const std::function<Future<R>(const T &)> &function, const std::shared_ptr<Promise<R>> &promise,
|
||||
const Future<T> &f) {
|
||||
if (f.IsError()) {
|
||||
promise->SetFailed(f.GetErrorCode());
|
||||
} else if (f.IsOK()) {
|
||||
promise->Associate(function(f.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename R>
|
||||
static void Then(const std::function<R(const T &)> &function, const std::shared_ptr<Promise<R>> &promise,
|
||||
const Future<T> &f) {
|
||||
if (f.IsError()) {
|
||||
promise->SetFailed(f.GetErrorCode());
|
||||
} else if (f.IsOK()) {
|
||||
promise->SetValue(function(f.Get()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void Afterf(const std::function<Future<T>(const Future<T> &)> &f, const std::shared_ptr<Promise<T>> &promise,
|
||||
const Future<T> &future) {
|
||||
promise->Associate(f(future));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void After(const std::shared_ptr<Promise<T>> &promise, const mindspore::Timer &timer, const Future<T> &future) {
|
||||
(void)mindspore::TimerTools::Cancel(timer);
|
||||
promise->Associate(future);
|
||||
}
|
||||
|
||||
void Waitf(const AID &aid);
|
||||
|
||||
void Wait(const AID &aid, const mindspore::Timer &timer);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_OPTION_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_OPTION_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "actor/buslog.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T>
|
||||
struct InnerSome {
|
||||
InnerSome(const T &t) : _t(std::move(t)) {}
|
||||
T _t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
InnerSome<typename std::decay<T>::type> Some(T &&t) {
|
||||
return InnerSome<typename std::decay<T>::type>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
struct None {};
|
||||
|
||||
template <typename T>
|
||||
class Option {
|
||||
public:
|
||||
Option() : data(), state(NONE) {}
|
||||
|
||||
Option(const T &t) : data(t), state(SOME) {}
|
||||
|
||||
Option(T &&t) : data(std::move(t)), state(SOME) {}
|
||||
|
||||
Option(const InnerSome<T> &some) : data(some._t), state(SOME) {}
|
||||
|
||||
Option(const None &none) : data(), state(NONE) {}
|
||||
|
||||
Option(const Option<T> &that) : data(), state(that.state) {
|
||||
if (that.IsSome()) {
|
||||
data = that.data;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~Option() {}
|
||||
|
||||
bool IsNone() const { return state == NONE; }
|
||||
|
||||
bool IsSome() const { return state == SOME; }
|
||||
|
||||
const T &Get() const & {
|
||||
BUS_ASSERT(IsSome());
|
||||
return data;
|
||||
}
|
||||
|
||||
T &&Get() && {
|
||||
BUS_ASSERT(IsSome());
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
const T &&Get() const && {
|
||||
BUS_ASSERT(IsSome());
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
// oprerator override
|
||||
Option<T> &operator=(const Option<T> &that) {
|
||||
if (&that != this) {
|
||||
state = that.state;
|
||||
if (that.IsSome()) {
|
||||
data = that.data;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Option<T> &that) const {
|
||||
return (IsNone() && that.IsNone()) || (IsSome() && that.IsSome() && data == that.data);
|
||||
}
|
||||
|
||||
bool operator!=(const Option<T> &that) const { return !(*this == that); }
|
||||
|
||||
bool operator==(const T &that) const { return IsSome() && data == that; }
|
||||
|
||||
bool operator!=(const T &that) const { return !(*this == that); }
|
||||
|
||||
private:
|
||||
enum State { NONE = 0, SOME = 1 };
|
||||
|
||||
T data;
|
||||
State state;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_RESULT_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_RESULT_H
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "option.h"
|
||||
#include "status.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename... Types>
|
||||
class Result {
|
||||
public:
|
||||
Result() : status(Status::KINIT) {}
|
||||
|
||||
Result(Types... types, const Status &s) : tuple(Option<Types>(types)...), status(s) {}
|
||||
|
||||
~Result() {}
|
||||
|
||||
template <std::size_t I>
|
||||
bool IsSome() {
|
||||
return (std::get<I>(tuple)).IsSome();
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
bool IsNone() {
|
||||
return std::get<I>(tuple).IsNone();
|
||||
}
|
||||
|
||||
bool IsOK() { return status.IsOK(); }
|
||||
|
||||
bool IsError() { return status.IsError(); }
|
||||
|
||||
void SetStatus(Status::Code code) { status.SetCode(code); }
|
||||
|
||||
const Status &GetStatus() const { return status; }
|
||||
|
||||
template <std::size_t I>
|
||||
typename std::tuple_element<I, std::tuple<Option<Types>...>>::type Get() const {
|
||||
return GetOption<I>().Get();
|
||||
}
|
||||
|
||||
private:
|
||||
template <std::size_t I>
|
||||
typename std::tuple_element<I, std::tuple<Option<Types>...>>::type GetOption() const {
|
||||
return std::get<I>(tuple);
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<Option<Types>...> tuple;
|
||||
Status status;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_SPINLOCK_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_SPINLOCK_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class SpinLock {
|
||||
public:
|
||||
void Lock() {
|
||||
while (locked.test_and_set(std::memory_order_acquire))
|
||||
;
|
||||
}
|
||||
|
||||
void Unlock() { locked.clear(std::memory_order_release); }
|
||||
|
||||
private:
|
||||
std::atomic_flag locked = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_STATUS_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_STATUS_H
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class Status {
|
||||
public:
|
||||
typedef int32_t Code;
|
||||
|
||||
static const Code KINIT = 1;
|
||||
static const Code KOK = 0;
|
||||
static const Code KERROR = -1;
|
||||
|
||||
// Create a success status.
|
||||
Status(int32_t c) : code(c) {}
|
||||
|
||||
Status() : code(KINIT) {}
|
||||
|
||||
virtual ~Status() {}
|
||||
|
||||
// Returns true iff the status indicates success.
|
||||
bool IsInit() const { return (code == KINIT); }
|
||||
|
||||
bool IsOK() const { return (code == KOK); }
|
||||
|
||||
bool IsError() const { return (code != KINIT && code != KOK); }
|
||||
|
||||
// Return a success status.
|
||||
Status OK() const { return Status(KOK); }
|
||||
|
||||
Status Error() const { return Status(KERROR); }
|
||||
|
||||
void SetError() {
|
||||
code = KERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
void SetOK() {
|
||||
code = KOK;
|
||||
return;
|
||||
}
|
||||
|
||||
Code GetCode() const { return code; }
|
||||
|
||||
void SetCode(Code c) { code = c; }
|
||||
|
||||
private:
|
||||
Code code;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_TRY_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_TRY_H
|
||||
|
||||
#include "async/failure.h"
|
||||
#include "async/option.h"
|
||||
#include "async/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
template <typename T, typename F = Failure>
|
||||
class Try {
|
||||
public:
|
||||
Try() : errorCode(Status::KOK) {}
|
||||
|
||||
Try(const T &t) {
|
||||
data = Some(t);
|
||||
errorCode = Status::KOK;
|
||||
}
|
||||
|
||||
Try(const F &errCode) { errorCode = errCode; }
|
||||
|
||||
virtual ~Try() {}
|
||||
|
||||
bool IsOK() { return !IsError(); }
|
||||
|
||||
bool IsError() { return data.IsNone(); }
|
||||
|
||||
const T &Get() const { return data.Get(); }
|
||||
|
||||
const int GetErrorCode() const { return errorCode.GetErrorCode(); }
|
||||
|
||||
private:
|
||||
Option<T> data;
|
||||
Failure errorCode;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_UUID_BASE_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_UUID_BASE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "async/option.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace uuids {
|
||||
|
||||
const std::size_t UUID_SIZE = 16;
|
||||
|
||||
struct uuid {
|
||||
public:
|
||||
static std::size_t Size();
|
||||
|
||||
static std::string ToBytes(const uuid &u);
|
||||
|
||||
static Option<uuid> FromBytes(const std::string &s);
|
||||
|
||||
static Option<unsigned char> GetValue(char c);
|
||||
|
||||
static Option<uuid> FromString(const std::string &s);
|
||||
|
||||
// To check whether uuid looks like 0000000-000-000-000-000000000000000
|
||||
bool IsNilUUID() const;
|
||||
|
||||
const uint8_t *Get() const;
|
||||
|
||||
private:
|
||||
const uint8_t *BeginAddress() const;
|
||||
|
||||
const uint8_t *EndAddress() const;
|
||||
|
||||
uint8_t *BeginAddress();
|
||||
|
||||
uint8_t *EndAddress();
|
||||
|
||||
friend class RandomBasedGenerator;
|
||||
friend bool operator==(uuid const &left, uuid const &right);
|
||||
friend bool operator!=(uuid const &left, uuid const &right);
|
||||
template <typename T, typename F>
|
||||
friend std::basic_ostream<T, F> &operator<<(std::basic_ostream<T, F> &s, const struct uuid &outputUuid);
|
||||
uint8_t uuidData[UUID_SIZE];
|
||||
};
|
||||
|
||||
class RandomBasedGenerator {
|
||||
public:
|
||||
static uuid GenerateRandomUuid();
|
||||
};
|
||||
|
||||
// operator override
|
||||
inline bool operator==(uuid const &left, uuid const &right) {
|
||||
return std::equal(left.BeginAddress(), left.EndAddress(), right.BeginAddress());
|
||||
}
|
||||
|
||||
// operator override
|
||||
inline bool operator!=(uuid const &left, uuid const &right) { return !(left == right); }
|
||||
|
||||
// operator override
|
||||
template <typename T, typename F>
|
||||
std::basic_ostream<T, F> &operator<<(std::basic_ostream<T, F> &s, const struct uuid &outputUuid) {
|
||||
const int FIRST_DELIM_OFFSET = 3;
|
||||
const int SECOND_DELIM_OFFSET = 5;
|
||||
const int THIRD_DELIM_OFFSET = 7;
|
||||
const int FOURTH_DELIM_OFFSET = 9;
|
||||
const int UUID_WIDTH = 2;
|
||||
s << std::hex << std::setfill(static_cast<T>('0'));
|
||||
|
||||
int i = 0;
|
||||
for (const uint8_t *ptr = outputUuid.BeginAddress(); ptr < outputUuid.EndAddress(); ++ptr, ++i) {
|
||||
s << std::setw(UUID_WIDTH) << (int)(*ptr);
|
||||
if (i == FIRST_DELIM_OFFSET || i == SECOND_DELIM_OFFSET || i == THIRD_DELIM_OFFSET || i == FOURTH_DELIM_OFFSET) {
|
||||
s << '-';
|
||||
}
|
||||
}
|
||||
|
||||
s << std::setfill(static_cast<T>(' ')) << std::dec;
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace uuids
|
||||
} // namespace mindspore
|
||||
|
||||
#endif /* UUID_BASE_HPP_ */
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_UUID_GENERATOR_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_UUID_GENERATOR_H
|
||||
|
||||
#include "uuid_base.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
namespace uuid_generator {
|
||||
struct UUID : public mindspore::uuids::uuid {
|
||||
public:
|
||||
explicit UUID(const mindspore::uuids::uuid &inputUUID) : mindspore::uuids::uuid(inputUUID) {}
|
||||
static UUID GetRandomUUID();
|
||||
std::string ToString();
|
||||
};
|
||||
} // namespace uuid_generator
|
||||
|
||||
namespace localid_generator {
|
||||
int GenLocalActorId();
|
||||
|
||||
#ifdef HTTP_ENABLED
|
||||
int GenHttpClientConnId();
|
||||
int GenHttpServerConnId();
|
||||
#endif
|
||||
|
||||
} // namespace localid_generator
|
||||
|
||||
} // namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_LITEBUS_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_LITEBUS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LITEBUS_URL_MAX_LEN 138
|
||||
|
||||
struct LitebusConfig {
|
||||
char tcpUrl[LITEBUS_URL_MAX_LEN];
|
||||
char tcpUrlAdv[LITEBUS_URL_MAX_LEN];
|
||||
char udpUrl[LITEBUS_URL_MAX_LEN];
|
||||
char udpUrlAdv[LITEBUS_URL_MAX_LEN];
|
||||
int threadCount;
|
||||
int httpKmsgFlag;
|
||||
};
|
||||
|
||||
int LitebusInitializeC(const struct LitebusConfig *config);
|
||||
|
||||
void LitebusFinalizeC();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_INCLUDE_LITEBUS_HPP_H
|
||||
#define MINDSPORE_CORE_MINDRT_INCLUDE_LITEBUS_HPP_H
|
||||
|
||||
#include <string>
|
||||
#include "mindrt/include/actor/actor.h"
|
||||
|
||||
// brief provide an asynchronous programming framework as Actor model
|
||||
namespace mindspore {
|
||||
|
||||
struct LitebusAddress {
|
||||
std::string scheme;
|
||||
std::string ip;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
// brief initialize the library
|
||||
int Initialize(const std::string &tcpUrl, const std::string &tcpUrlAdv = "", const std::string &udpUrl = "",
|
||||
const std::string &udpUrlAdv = "", int threadCount = 0);
|
||||
|
||||
// brief spawn a process to run an actor
|
||||
AID Spawn(ActorReference actor, bool sharedThread = true, bool start = true);
|
||||
|
||||
// brief wait for the actor process to exit . It will be discarded
|
||||
void Await(const ActorReference &actor);
|
||||
|
||||
// brief get actor with aid
|
||||
ActorReference GetActor(const AID &actor);
|
||||
|
||||
// brief wait for the actor process to exit
|
||||
void Await(const AID &actor);
|
||||
|
||||
// brief Terminate the actor to exit
|
||||
void Terminate(const AID &actor);
|
||||
|
||||
// brief set the actor's running status
|
||||
void SetActorStatus(const AID &actor, bool start);
|
||||
|
||||
// brief Terminate all actors
|
||||
void TerminateAll();
|
||||
|
||||
// brief terminate the process. It will be discarded
|
||||
void Finalize();
|
||||
|
||||
// brief set the delegate of restful
|
||||
void SetDelegate(const std::string &delegate);
|
||||
|
||||
// set log pid of the process use litebus
|
||||
void SetLogPID(HARES_LOG_PID pid);
|
||||
|
||||
// get global litebus address
|
||||
const LitebusAddress &GetLitebusAddress();
|
||||
|
||||
// get flag of http message format
|
||||
int GetHttpKmsgFlag();
|
||||
|
||||
// brief set flag of http message format
|
||||
void SetHttpKmsgFlag(int flag);
|
||||
|
||||
} // namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 __LITEBUS_DURATION_HPP__
|
||||
#define __LITEBUS_DURATION_HPP__
|
||||
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "async/spinlock.h"
|
||||
|
||||
namespace mindspore {
|
||||
using Duration = uint64_t;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 __LITEBUS_TIMER_HPP__
|
||||
#define __LITEBUS_TIMER_HPP__
|
||||
|
||||
#include "actor/aid.h"
|
||||
#include "timer/timewatch.h"
|
||||
|
||||
namespace mindspore {
|
||||
class Timer {
|
||||
public:
|
||||
Timer();
|
||||
~Timer();
|
||||
bool operator==(const Timer &that) const;
|
||||
// run this timer's thunk.
|
||||
void operator()() const;
|
||||
TimeWatch GetTimeWatch() const;
|
||||
AID GetTimerAID() const;
|
||||
uint64_t GetTimerID() const;
|
||||
|
||||
private:
|
||||
friend class TimerTools;
|
||||
|
||||
Timer(uint64_t timerId, const TimeWatch &timeWatch, const AID &timeAid, const std::function<void()> &handler);
|
||||
|
||||
uint64_t id;
|
||||
TimeWatch t;
|
||||
AID aid;
|
||||
std::function<void()> thunk;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 __LITEBUS_TIMETOOLS_HPP__
|
||||
#define __LITEBUS_TIMETOOLS_HPP__
|
||||
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "timer/duration.h"
|
||||
#include "timer/timer.h"
|
||||
|
||||
namespace mindspore {
|
||||
class TimerTools {
|
||||
public:
|
||||
static bool Initialize();
|
||||
static void Finalize();
|
||||
static Timer AddTimer(const Duration &duration, const AID &aid, const std::function<void()> &thunk);
|
||||
static bool Cancel(const Timer &timer);
|
||||
static std::atomic_bool g_initStatus;
|
||||
};
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 __LITEBUS_TIMEWATCH_HPP__
|
||||
#define __LITEBUS_TIMEWATCH_HPP__
|
||||
|
||||
#include "timer/duration.h"
|
||||
namespace mindspore {
|
||||
constexpr Duration MICRTONANO = 1000;
|
||||
constexpr Duration MILLITOMICR = 1000;
|
||||
constexpr Duration SECTOMILLI = 1000;
|
||||
|
||||
class TimeWatch {
|
||||
public:
|
||||
TimeWatch();
|
||||
|
||||
TimeWatch(const Duration &duration);
|
||||
|
||||
TimeWatch(const TimeWatch &that);
|
||||
~TimeWatch();
|
||||
|
||||
// Constructs a Time instance that is the 'duration' from now.
|
||||
static TimeWatch In(const Duration &duration);
|
||||
|
||||
static Duration Now();
|
||||
|
||||
TimeWatch &operator=(const TimeWatch &that);
|
||||
|
||||
TimeWatch &operator=(const Duration &duration);
|
||||
|
||||
bool operator==(const TimeWatch &that) const;
|
||||
|
||||
bool operator<(const TimeWatch &that) const;
|
||||
|
||||
bool operator<=(const TimeWatch &that) const;
|
||||
|
||||
// Returns the value of the timewatch as a Duration object.
|
||||
Duration Time() const;
|
||||
|
||||
// Returns the amount of time remaining.
|
||||
Duration Remaining() const;
|
||||
|
||||
// return true if the time expired.
|
||||
bool Expired() const;
|
||||
|
||||
private:
|
||||
Duration duration;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,131 @@
|
|||
# include DIRECTIVES FOR LITEBUS LIBRARY (generates, e.g., -I/path/to/thing on Linux).
|
||||
######################################################################################
|
||||
if(${HTTP_ENABLED} STREQUAL "on")
|
||||
set(LITEBUS_INCLUDE_DIR ${LITEBUS_INCLUDE_DIR} ${HTTP_PARSER_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if(${SSL_ENABLED} STREQUAL "on")
|
||||
set(LITEBUS_INCLUDE_DIR ${LITEBUS_INCLUDE_DIR}
|
||||
${LITEBUS_OSSCRYPTO_INCLUDE_DIR}
|
||||
${LITEBUS_HARESCRYPTO_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
link_directories(${SECUREC_LIB_DIR})
|
||||
link_directories(${GLOG_LIB_DIR})
|
||||
link_directories(${HARES_LOG_LIB_DIR})
|
||||
link_directories(${PROTOBUF_C_LIB_DIR})
|
||||
|
||||
if(${HTTP_ENABLED} STREQUAL "on")
|
||||
link_directories(${HTTP_PARSER_LIB_DIR})
|
||||
endif()
|
||||
|
||||
# LINK libgcov.a
|
||||
#######################################################################
|
||||
if(${CODE_COVERAGE} STREQUAL "on")
|
||||
set(LINK_LIBS ${LINK_LIBS} gcov)
|
||||
endif()
|
||||
|
||||
# add object lib to avoid duplicate compile for a single source file
|
||||
#######################################################################
|
||||
add_library(litebus_obj OBJECT litebus.cc)
|
||||
target_include_directories(litebus_obj PUBLIC ${LITEBUS_INCLUDE_DIR} ${3RDPARTY_LITEBUS_INCLUDE_DIRS})
|
||||
#add_library(decrypt_obj OBJECT)
|
||||
|
||||
# THE LITEBUS LIBRARY (generates, e.g., liblitebus.so, etc., on Linux).
|
||||
#######################################################################
|
||||
if(${STATIC_LIB} STREQUAL "on")
|
||||
|
||||
#######################################################################
|
||||
add_library(${LITEBUS_TARGET}_static STATIC $<TARGET_OBJECTS:litebus_obj>)
|
||||
target_link_libraries(${LITEBUS_TARGET}_static ${LINK_LIBS} ${LITEBUS_HARES_DECRYPT_SLIB}
|
||||
${OPENSSL_SSL_LIB_A} ${OPENSSL_CRYPTO_LIB_A})
|
||||
set_target_properties(${LITEBUS_TARGET}_static PROPERTIES OUTPUT_NAME ${LITEBUS_TARGET})
|
||||
|
||||
if(DEFINED DEPEND_PATH)
|
||||
add_custom_command(TARGET ${LITEBUS_TARGET}_static POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink lib${LITEBUS_TARGET}.a liblitebus.a
|
||||
)
|
||||
endif()
|
||||
|
||||
#######################################################################
|
||||
endif()
|
||||
|
||||
set(LINK_LIBS ${LINK_LIBS})
|
||||
|
||||
if(${HTTP_ENABLED} STREQUAL "on")
|
||||
set(LINK_LIBS ${LINK_LIBS} ${HTTP_PARSER_DFLAG})
|
||||
endif()
|
||||
|
||||
add_library(litebus_shared SHARED $<TARGET_OBJECTS:litebus_obj>)
|
||||
target_link_libraries(litebus_shared ${LINK_LIBS})
|
||||
target_include_directories(litebus_shared PUBLIC ${LITEBUS_INCLUDE_DIR} ${3RDPARTY_LITEBUS_INCLUDE_DIRS})
|
||||
|
||||
set_target_properties(
|
||||
litebus_shared PROPERTIES
|
||||
OUTPUT_NAME litebus
|
||||
VERSION ${LITEBUS_PACKAGE_VERSION}
|
||||
SOVERSION ${LITEBUS_PACKAGE_VERSION}
|
||||
LINK_FLAGS -s
|
||||
)
|
||||
|
||||
#copy lib to depend path (internal use)
|
||||
#set(DEPEND_PATH "${PROJECT_SOURCE_DIR}/output1")
|
||||
if(DEFINED DEPEND_PATH)
|
||||
set(DEPEND_LIB_PATH ${DEPEND_PATH}/LITEBUS/lib)
|
||||
set(DEPEND_INCLUDE_PATH ${DEPEND_PATH}/LITEBUS/include)
|
||||
|
||||
add_custom_target(litebus_all ALL COMMENT "================= litebus_all =====================")
|
||||
if(${STATIC_LIB} STREQUAL "on")
|
||||
add_dependencies(litebus_all litebus_shared ${LITEBUS_TARGET}_static)
|
||||
endif()
|
||||
add_dependencies(litebus_all litebus_shared)
|
||||
add_custom_command(TARGET litebus_all POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/MakeDirectory.cmake
|
||||
${DEPEND_LIB_PATH} ${DEPEND_INCLUDE_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -DLITEBUS_COPYTO="${DEPEND_LIB_PATH}" -P
|
||||
${PROJECT_SOURCE_DIR}/cmake/CopyLibToPath.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/litebus.hpp
|
||||
${DEPEND_INCLUDE_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/include/litebus.h
|
||||
${DEPEND_INCLUDE_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include/actor
|
||||
${DEPEND_INCLUDE_PATH}/actor
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include/async
|
||||
${DEPEND_INCLUDE_PATH}/async
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include/timer
|
||||
${DEPEND_INCLUDE_PATH}/timer
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include/exec
|
||||
${DEPEND_INCLUDE_PATH}/exec
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include/utils
|
||||
${DEPEND_INCLUDE_PATH}/utils)
|
||||
if(${HTTP_ENABLED} STREQUAL "on")
|
||||
add_custom_command(TARGET litebus_all POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${PROJECT_SOURCE_DIR}/include/httpd ${DEPEND_INCLUDE_PATH}/httpd)
|
||||
endif()
|
||||
if(${SSL_ENABLED} STREQUAL "on")
|
||||
add_custom_command(TARGET litebus_all POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${PROJECT_SOURCE_DIR}/include/ssl ${DEPEND_INCLUDE_PATH}/ssl)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
#install lib to package path
|
||||
if("${PROJECT_HARES}" STREQUAL "cloudcore")
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_LS_Master/lib PERMISSIONS OWNER_READ)
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_LS_Slave/lib PERMISSIONS OWNER_READ)
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_HASEN_Common/lib PERMISSIONS OWNER_READ)
|
||||
elseif("${PROJECT_HARES}" STREQUAL "hasen_cloudcore_csp")
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_Common/lib PERMISSIONS OWNER_READ)
|
||||
else()
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_Common/lib PERMISSIONS OWNER_READ)
|
||||
install(TARGETS litebus_shared LIBRARY DESTINATION HARES_Slave/lib PERMISSIONS OWNER_READ)
|
||||
endif()
|
||||
|
||||
# Build pbjson.so.
|
||||
add_subdirectory(actor)
|
||||
add_subdirectory(async)
|
||||
add_subdirectory(evloop)
|
||||
add_subdirectory(timer)
|
|
@ -0,0 +1,8 @@
|
|||
target_sources(litebus_obj PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/actor.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/actormgr.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/actorthread.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/actorpolicy.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/aid.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysmgr_actor.cc
|
||||
)
|
|
@ -0,0 +1,221 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "actor/actor.h"
|
||||
#include "actor/actormgr.h"
|
||||
#include "actor/actorpolicyinterface.h"
|
||||
#include "actor/iomgr.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
ActorBase::ActorBase(const std::string &name)
|
||||
: actorThread(nullptr), id(name, ActorMgr::GetActorMgrRef()->GetUrl()), actionFunctions() {}
|
||||
|
||||
ActorBase::~ActorBase() {}
|
||||
|
||||
void ActorBase::Spawn(std::shared_ptr<ActorBase> &actor, std::unique_ptr<ActorPolicy> thread) {
|
||||
// lock here or await(). and unlock at Quit() or at aweit.
|
||||
waiterLock.lock();
|
||||
|
||||
actorThread = std::move(thread);
|
||||
}
|
||||
void ActorBase::SetRunningStatus(bool start) { actorThread->SetRunningStatus(start); }
|
||||
|
||||
void ActorBase::Await() {
|
||||
std::string actorName = id.Name();
|
||||
// lock here or at spawn(). and unlock here or at worker(). wait for the worker to finish.
|
||||
MS_LOG(DEBUG) << "ACTOR is waiting for terminate to finish. a=" << actorName.c_str();
|
||||
|
||||
waiterLock.lock();
|
||||
waiterLock.unlock();
|
||||
MS_LOG(DEBUG) << "ACTOR succeeded in waiting. a=" << actorName.c_str();
|
||||
}
|
||||
void ActorBase::Terminate() {
|
||||
std::unique_ptr<MessageBase> msg(new (std::nothrow) MessageBase("Terminate", MessageBase::Type::KTERMINATE));
|
||||
BUS_OOM_EXIT(msg);
|
||||
(void)EnqueMessage(std::move(msg));
|
||||
}
|
||||
|
||||
void ActorBase::HandlekMsg(std::unique_ptr<MessageBase> &msg) {
|
||||
auto it = actionFunctions.find(msg->Name());
|
||||
if (it != actionFunctions.end()) {
|
||||
ActorFunction &func = it->second;
|
||||
func(msg);
|
||||
} else {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_WARNING, PID_LITEBUS_LOG,
|
||||
"ACTOR can not find function for message (%s)", "a=%s,m=%s", id.Name().c_str(),
|
||||
msg->Name().c_str());
|
||||
MS_LOG(WARNING) << "ACTOR can not find function for message, a=" << id.Name().c_str()
|
||||
<< ",m=" << msg->Name().c_str();
|
||||
}
|
||||
}
|
||||
int ActorBase::EnqueMessage(std::unique_ptr<MessageBase> msg) { return actorThread->EnqueMessage(msg); }
|
||||
|
||||
void ActorBase::Quit() {
|
||||
Finalize();
|
||||
actorThread->Terminate(this);
|
||||
// lock at spawn(), unlock here.
|
||||
waiterLock.unlock();
|
||||
}
|
||||
|
||||
void ActorBase::Run() {
|
||||
for (;;) {
|
||||
auto msgs = actorThread->GetMsgs();
|
||||
if (msgs == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (auto it = msgs->begin(); it != msgs->end(); ++it) {
|
||||
std::unique_ptr<MessageBase> &msg = *it;
|
||||
if (msg == nullptr) {
|
||||
continue;
|
||||
}
|
||||
// std::cout << "dequeue message]actor=" << id.Name() << ",msg=" << msg->Name() << std::endl;
|
||||
AddMsgRecord(msg->Name());
|
||||
switch (msg->GetType()) {
|
||||
case MessageBase::Type::KMSG:
|
||||
case MessageBase::Type::KUDP: {
|
||||
if (Filter(msg)) {
|
||||
continue;
|
||||
}
|
||||
this->HandlekMsg(msg);
|
||||
break;
|
||||
}
|
||||
case MessageBase::Type::KHTTP: {
|
||||
this->HandleHttp(std::move(msg));
|
||||
break;
|
||||
}
|
||||
case MessageBase::Type::KASYNC: {
|
||||
msg->Run(this);
|
||||
break;
|
||||
}
|
||||
case MessageBase::Type::KLOCAL: {
|
||||
this->HandleLocalMsg(std::move(msg));
|
||||
break;
|
||||
}
|
||||
case MessageBase::Type::KTERMINATE: {
|
||||
this->Quit();
|
||||
return;
|
||||
}
|
||||
case MessageBase::Type::KEXIT: {
|
||||
this->Exited(msg->From());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
msgs->clear();
|
||||
}
|
||||
}
|
||||
|
||||
int ActorBase::Send(const AID &to, std::unique_ptr<MessageBase> msg) {
|
||||
msg->SetFrom(id);
|
||||
return ActorMgr::GetActorMgrRef()->Send(to, std::move(msg));
|
||||
}
|
||||
int ActorBase::Send(const AID &to, std::string &&name, std::string &&strMsg, bool remoteLink, bool isExactNotRemote) {
|
||||
std::unique_ptr<MessageBase> msg(
|
||||
new (std::nothrow) MessageBase(this->id, to, std::move(name), std::move(strMsg), MessageBase::Type::KMSG));
|
||||
BUS_OOM_EXIT(msg);
|
||||
return ActorMgr::GetActorMgrRef()->Send(to, std::move(msg), remoteLink, isExactNotRemote);
|
||||
}
|
||||
|
||||
// register the message handle
|
||||
void ActorBase::Receive(const std::string &msgName, ActorFunction &&func) {
|
||||
if (actionFunctions.find(msgName) != actionFunctions.end()) {
|
||||
MS_LOG(ERROR) << "ACTOR function's name conflicts, a=%s" << id.Name().c_str() << ",f=%s" << msgName.c_str();
|
||||
BUS_EXIT("function's name conflicts");
|
||||
return;
|
||||
}
|
||||
actionFunctions.emplace(msgName, std::move(func));
|
||||
return;
|
||||
}
|
||||
|
||||
int ActorBase::Link(const AID &to) {
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
if (to.OK()) {
|
||||
io->Link(this->GetAID(), to);
|
||||
return ERRORCODE_SUCCESS;
|
||||
} else {
|
||||
return ACTOR_PARAMER_ERR;
|
||||
}
|
||||
} else {
|
||||
return IO_NOT_FIND;
|
||||
}
|
||||
}
|
||||
int ActorBase::UnLink(const AID &to) {
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
if (to.OK()) {
|
||||
io->UnLink(to);
|
||||
return ERRORCODE_SUCCESS;
|
||||
} else {
|
||||
return ACTOR_PARAMER_ERR;
|
||||
}
|
||||
} else {
|
||||
return IO_NOT_FIND;
|
||||
}
|
||||
}
|
||||
|
||||
int ActorBase::Reconnect(const AID &to) {
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
if (to.OK()) {
|
||||
io->Reconnect(this->GetAID(), to);
|
||||
return ERRORCODE_SUCCESS;
|
||||
} else {
|
||||
return ACTOR_PARAMER_ERR;
|
||||
}
|
||||
} else {
|
||||
return IO_NOT_FIND;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ActorBase::GetOutBufSize(const AID &to) {
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
return io->GetOutBufSize();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ActorBase::GetInBufSize(const AID &to) {
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
return io->GetInBufSize();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ActorBase::AddRuleUdp(const std::string &peer, int recordNum) {
|
||||
const std::string udp = BUS_UDP;
|
||||
auto io = ActorMgr::GetIOMgrRef(udp);
|
||||
if (io != nullptr) {
|
||||
return io->AddRuleUdp(peer, recordNum);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ActorBase::DelRuleUdp(const std::string &peer, bool outputLog) {
|
||||
const std::string udp = BUS_UDP;
|
||||
auto io = ActorMgr::GetIOMgrRef(udp);
|
||||
if (io != nullptr) {
|
||||
io->DelRuleUdp(peer, outputLog);
|
||||
}
|
||||
}
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "actor/actormgr.h"
|
||||
#include "actor/actorpolicy.h"
|
||||
#include "actor/iomgr.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
std::shared_ptr<ActorMgr> ActorMgr::actorMgr = std::make_shared<ActorMgr>();
|
||||
std::map<std::string, std::shared_ptr<IOMgr>> ActorMgr::ioMgrs;
|
||||
|
||||
std::shared_ptr<IOMgr> &ActorMgr::GetIOMgrRef(const std::string &protocol) {
|
||||
auto it = ioMgrs.find(protocol);
|
||||
if (it != ioMgrs.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
MS_LOG(DEBUG) << "Can't find IOMgr of protocol " << protocol.c_str();
|
||||
static std::shared_ptr<IOMgr> nullIOMgr;
|
||||
return nullIOMgr;
|
||||
}
|
||||
}
|
||||
ActorMgr::ActorMgr() : actors(), procotols(), urls() {
|
||||
actors.clear();
|
||||
procotols.clear();
|
||||
urls.clear();
|
||||
}
|
||||
|
||||
ActorMgr::~ActorMgr() {}
|
||||
|
||||
const std::string ActorMgr::GetUrl(const std::string &protocol) {
|
||||
auto it = procotols.find(protocol);
|
||||
if (it != procotols.end()) {
|
||||
return it->second;
|
||||
} else if (procotols.size() > 0) {
|
||||
return procotols.begin()->second;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void ActorMgr::AddUrl(const std::string &protocol, const std::string &url) {
|
||||
procotols[protocol] = url;
|
||||
AID id("a@" + url);
|
||||
(void)urls.insert(id.GetIp() + ":" + std::to_string(id.GetPort()));
|
||||
(void)urls.insert(id.GetProtocol() + "://" + id.GetIp() + ":" + std::to_string(id.GetPort()));
|
||||
(void)urls.insert(std::string("127.0.0.1:") + std::to_string(id.GetPort()));
|
||||
(void)urls.insert(protocol + "://127.0.0.1:" + std::to_string(id.GetPort()));
|
||||
}
|
||||
|
||||
void ActorMgr::AddIOMgr(const std::string &protocol, const std::shared_ptr<IOMgr> &ioMgr) { ioMgrs[protocol] = ioMgr; }
|
||||
|
||||
void ActorMgr::RemoveActor(const std::string &name) {
|
||||
MS_LOG(DEBUG) << "ACTOR was terminated with aid= " << name.c_str();
|
||||
actorsMutex.lock();
|
||||
(void)actors.erase(name);
|
||||
actorsMutex.unlock();
|
||||
}
|
||||
|
||||
void ActorMgr::TerminateAll() {
|
||||
// copy all the actors
|
||||
std::list<ActorReference> actorsWaiting;
|
||||
actorsMutex.lock();
|
||||
for (auto actorIt = actors.begin(); actorIt != actors.end(); ++actorIt) {
|
||||
actorsWaiting.push_back(actorIt->second);
|
||||
}
|
||||
actorsMutex.unlock();
|
||||
|
||||
// send terminal msg to all actors.
|
||||
for (auto actorIt = actorsWaiting.begin(); actorIt != actorsWaiting.end(); ++actorIt) {
|
||||
std::unique_ptr<MessageBase> msg(new (std::nothrow) MessageBase("Terminate", MessageBase::Type::KTERMINATE));
|
||||
BUS_OOM_EXIT(msg);
|
||||
(void)(*actorIt)->EnqueMessage(std::move(msg));
|
||||
(*actorIt)->SetRunningStatus(true);
|
||||
}
|
||||
|
||||
// wait actor's thread to finish.
|
||||
for (auto actorIt = actorsWaiting.begin(); actorIt != actorsWaiting.end(); ++actorIt) {
|
||||
(*actorIt)->Await();
|
||||
}
|
||||
}
|
||||
|
||||
void ActorMgr::Initialize(int threadCount) { threadPool.AddThread(threadCount); }
|
||||
|
||||
void ActorMgr::Finalize() {
|
||||
this->TerminateAll();
|
||||
MS_LOG(INFO) << "litebus Actors finish exiting.";
|
||||
|
||||
// stop all actor threads;
|
||||
threadPool.Finalize();
|
||||
MS_LOG(INFO) << "litebus Threads finish exiting.";
|
||||
|
||||
// stop iomgr thread
|
||||
for (auto mgrIt = ioMgrs.begin(); mgrIt != ioMgrs.end(); ++mgrIt) {
|
||||
MS_LOG(INFO) << "finalize IOMgr=" << mgrIt->first.c_str();
|
||||
mgrIt->second->Finish();
|
||||
}
|
||||
|
||||
MS_LOG(INFO) << "litebus IOMGRS finish exiting.";
|
||||
}
|
||||
|
||||
ActorReference ActorMgr::GetActor(const AID &id) {
|
||||
ActorReference result;
|
||||
actorsMutex.lock();
|
||||
auto actorIt = actors.find(id.Name());
|
||||
if (actorIt != actors.end()) {
|
||||
result = actorIt->second;
|
||||
} else {
|
||||
MS_LOG(DEBUG) << "can't find ACTOR with name=" << id.Name().c_str();
|
||||
result = nullptr;
|
||||
}
|
||||
// find the
|
||||
actorsMutex.unlock();
|
||||
return result;
|
||||
}
|
||||
int ActorMgr::Send(const AID &to, std::unique_ptr<MessageBase> msg, bool remoteLink, bool isExactNotRemote) {
|
||||
// The destination is local
|
||||
if (IsLocalAddres(to)) {
|
||||
auto actor = GetActor(to);
|
||||
if (actor != nullptr) {
|
||||
if (to.GetProtocol() == BUS_UDP && msg->GetType() == MessageBase::Type::KMSG) {
|
||||
msg->type = MessageBase::Type::KUDP;
|
||||
}
|
||||
return actor->EnqueMessage(std::move(msg));
|
||||
} else {
|
||||
return ACTOR_NOT_FIND;
|
||||
}
|
||||
|
||||
} else {
|
||||
// send to remote actor
|
||||
if (msg->GetType() != MessageBase::Type::KMSG) {
|
||||
MS_LOG(ERROR) << "The msg is not KMSG,it can't send to remote=" << std::string(to).c_str();
|
||||
return ACTOR_PARAMER_ERR;
|
||||
} else {
|
||||
// null
|
||||
}
|
||||
msg->SetTo(to);
|
||||
auto io = ActorMgr::GetIOMgrRef(to);
|
||||
if (io != nullptr) {
|
||||
return io->Send(std::move(msg), remoteLink, isExactNotRemote);
|
||||
} else {
|
||||
MS_LOG(ERROR) << "The protocol is not supported:"
|
||||
<< "p=" << to.GetProtocol().c_str() << ",f=" << msg->From().Name().c_str()
|
||||
<< ",t=" << to.Name().c_str() << ",m=" << msg->Name().c_str();
|
||||
return IO_NOT_FIND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AID ActorMgr::Spawn(ActorReference &actor, bool shareThread, bool start) {
|
||||
actorsMutex.lock();
|
||||
if (actors.find(actor->GetAID().Name()) != actors.end()) {
|
||||
actorsMutex.unlock();
|
||||
MS_LOG(ERROR) << "The actor's name conflicts,name:" << actor->GetAID().Name().c_str();
|
||||
BUS_EXIT("Actor name conflicts.");
|
||||
}
|
||||
|
||||
MS_LOG(DEBUG) << "ACTOR was spawned,a=" << actor->GetAID().Name().c_str();
|
||||
|
||||
std::unique_ptr<ActorPolicy> threadPolicy;
|
||||
|
||||
if (shareThread) {
|
||||
threadPolicy.reset(new (std::nothrow) ShardedThread(actor));
|
||||
BUS_OOM_EXIT(threadPolicy);
|
||||
actor->Spawn(actor, std::move(threadPolicy));
|
||||
|
||||
} else {
|
||||
threadPolicy.reset(new (std::nothrow) SingleThread());
|
||||
BUS_OOM_EXIT(threadPolicy);
|
||||
actor->Spawn(actor, std::move(threadPolicy));
|
||||
ActorMgr::GetActorMgrRef()->SetActorReady(actor);
|
||||
}
|
||||
|
||||
(void)this->actors.emplace(actor->GetAID().Name(), actor);
|
||||
actorsMutex.unlock();
|
||||
|
||||
// long time
|
||||
actor->Init();
|
||||
|
||||
actor->SetRunningStatus(start);
|
||||
|
||||
return actor->GetAID();
|
||||
}
|
||||
|
||||
void ActorMgr::Terminate(const AID &id) {
|
||||
auto actor = GetActor(id);
|
||||
if (actor != nullptr) {
|
||||
std::unique_ptr<MessageBase> msg(new (std::nothrow) MessageBase("Terminate", MessageBase::Type::KTERMINATE));
|
||||
BUS_OOM_EXIT(msg);
|
||||
(void)actor->EnqueMessage(std::move(msg));
|
||||
actor->SetRunningStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ActorMgr::SetActorStatus(const AID &pid, bool start) {
|
||||
auto actor = GetActor(pid);
|
||||
if (actor != nullptr) {
|
||||
actor->SetRunningStatus(start);
|
||||
}
|
||||
}
|
||||
|
||||
void ActorMgr::Wait(const AID &id) {
|
||||
auto actor = GetActor(id);
|
||||
if (actor != nullptr) {
|
||||
actor->Await();
|
||||
}
|
||||
}
|
||||
|
||||
}; // end of namespace mindspore
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORMGR_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORMGR_H
|
||||
|
||||
#include <set>
|
||||
#include "actor/actorthread.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class ActorBase;
|
||||
class IOMgr;
|
||||
|
||||
class ActorMgr {
|
||||
public:
|
||||
static inline std::shared_ptr<ActorMgr> &GetActorMgrRef() { return actorMgr; }
|
||||
|
||||
static std::shared_ptr<IOMgr> &GetIOMgrRef(const std::string &protocol = "tcp");
|
||||
|
||||
static inline std::shared_ptr<IOMgr> &GetIOMgrRef(const AID &to) { return GetIOMgrRef(to.GetProtocol()); }
|
||||
|
||||
static void Receive(std::unique_ptr<MessageBase> &&msg) {
|
||||
auto to = msg->To().Name();
|
||||
(void)ActorMgr::GetActorMgrRef()->Send(to, std::move(msg));
|
||||
}
|
||||
|
||||
ActorMgr();
|
||||
~ActorMgr();
|
||||
|
||||
void Finalize();
|
||||
void Initialize(int threadCount);
|
||||
void RemoveActor(const std::string &name);
|
||||
ActorReference GetActor(const AID &id);
|
||||
const std::string GetUrl(const std::string &protocol = "tcp");
|
||||
void AddUrl(const std::string &protocol, const std::string &url);
|
||||
void AddIOMgr(const std::string &protocol, const std::shared_ptr<IOMgr> &ioMgr);
|
||||
int Send(const AID &to, std::unique_ptr<MessageBase> msg, bool remoteLink = false, bool isExactNotRemote = false);
|
||||
AID Spawn(ActorReference &actor, bool shareThread = true, bool start = true);
|
||||
void Terminate(const AID &id);
|
||||
void TerminateAll();
|
||||
void Wait(const AID &pid);
|
||||
inline const std::string &GetDelegate() const { return delegate; }
|
||||
|
||||
inline void SetDelegate(const std::string &d) { delegate = d; }
|
||||
inline void SetActorReady(const std::shared_ptr<ActorBase> &actor) { threadPool.EnqueReadyActor(actor); }
|
||||
void SetActorStatus(const AID &pid, bool start);
|
||||
|
||||
private:
|
||||
inline bool IsLocalAddres(const AID &id) {
|
||||
if (id.Url() == "" || id.Url().empty() || urls.find(id.Url()) != urls.end()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Map of all local spawned and running processes.
|
||||
std::map<std::string, ActorReference> actors;
|
||||
std::mutex actorsMutex;
|
||||
|
||||
ActorThread threadPool;
|
||||
|
||||
std::map<std::string, std::string> procotols;
|
||||
std::set<std::string> urls;
|
||||
std::string delegate;
|
||||
static std::shared_ptr<ActorMgr> actorMgr;
|
||||
static std::map<std::string, std::shared_ptr<IOMgr> > ioMgrs;
|
||||
|
||||
}; // end of class ActorMgr
|
||||
|
||||
}; // end of namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "actor/actor.h"
|
||||
#include "actor/actormgr.h"
|
||||
#include "actor/actorpolicy.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
void ActorPolicy::SetRunningStatus(bool startRun) {
|
||||
std::lock_guard<std::mutex> lock(mailboxLock);
|
||||
this->start = startRun;
|
||||
Notify();
|
||||
}
|
||||
|
||||
SingleThread::SingleThread() {}
|
||||
SingleThread::~SingleThread() {}
|
||||
|
||||
void SingleThread::Terminate(const ActorBase *actor) {
|
||||
std::string actorName = actor->GetAID().Name();
|
||||
MS_LOG(DEBUG) << "ACTOR SingleThread received terminate message, v=" << actorName.c_str();
|
||||
// remove actor from actorMgr
|
||||
ActorMgr::GetActorMgrRef()->RemoveActor(actorName);
|
||||
}
|
||||
|
||||
int SingleThread::EnqueMessage(std::unique_ptr<MessageBase> &msg) {
|
||||
int result;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mailboxLock);
|
||||
enqueMailbox->push_back(std::move(msg));
|
||||
result = ++msgCount;
|
||||
}
|
||||
|
||||
// Notify when the count of message is from empty to one.
|
||||
if (start && result == 1) {
|
||||
conditionVar.notify_one();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
void SingleThread::Notify() {
|
||||
if (start && msgCount > 0) {
|
||||
conditionVar.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<MessageBase>> *SingleThread::GetMsgs() {
|
||||
std::list<std::unique_ptr<MessageBase>> *result;
|
||||
std::unique_lock<std::mutex> lock(mailboxLock);
|
||||
conditionVar.wait(lock, [this] { return (!this->enqueMailbox->empty()); });
|
||||
SwapMailbox();
|
||||
|
||||
// REF_PRIVATE_MEMBER
|
||||
result = dequeMailbox;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ShardedThread::ShardedThread(const std::shared_ptr<ActorBase> &aActor)
|
||||
: ready(false), terminated(false), actor(aActor) {}
|
||||
ShardedThread::~ShardedThread() {}
|
||||
|
||||
void ShardedThread::Terminate(const ActorBase *aActor) {
|
||||
std::string actorName = aActor->GetAID().Name();
|
||||
MS_LOG(DEBUG) << "ACTOR ShardedThread received terminate message,v=" << actorName.c_str();
|
||||
// remove actor from actorMgr
|
||||
ActorMgr::GetActorMgrRef()->RemoveActor(actorName);
|
||||
|
||||
mailboxLock.lock();
|
||||
terminated = true;
|
||||
this->actor = nullptr;
|
||||
mailboxLock.unlock();
|
||||
}
|
||||
|
||||
int ShardedThread::EnqueMessage(std::unique_ptr<MessageBase> &msg) {
|
||||
int result;
|
||||
mailboxLock.lock();
|
||||
enqueMailbox->push_back(std::move(msg));
|
||||
// true : The actor is running. else the actor will be ready to run.
|
||||
if (start && ready == false && terminated == false) {
|
||||
ActorMgr::GetActorMgrRef()->SetActorReady(actor);
|
||||
ready = true;
|
||||
}
|
||||
result = ++msgCount;
|
||||
mailboxLock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShardedThread::Notify() {
|
||||
if (start && ready == false && terminated == false && msgCount > 0) {
|
||||
ActorMgr::GetActorMgrRef()->SetActorReady(actor);
|
||||
ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<MessageBase>> *ShardedThread::GetMsgs() {
|
||||
std::list<std::unique_ptr<MessageBase>> *result;
|
||||
mailboxLock.lock();
|
||||
|
||||
if (enqueMailbox->empty()) {
|
||||
ready = false;
|
||||
result = nullptr;
|
||||
} else {
|
||||
ready = true;
|
||||
SwapMailbox();
|
||||
result = dequeMailbox;
|
||||
}
|
||||
|
||||
mailboxLock.unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}; // end of namespace mindspore
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORPOLICY_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORPOLICY_H
|
||||
#include "actor/actorpolicyinterface.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class ShardedThread : public ActorPolicy {
|
||||
public:
|
||||
ShardedThread(const std::shared_ptr<ActorBase> &actor);
|
||||
virtual ~ShardedThread();
|
||||
|
||||
protected:
|
||||
virtual void Terminate(const ActorBase *actor);
|
||||
virtual int EnqueMessage(std::unique_ptr<MessageBase> &msg);
|
||||
virtual std::list<std::unique_ptr<MessageBase>> *GetMsgs();
|
||||
virtual void Notify();
|
||||
|
||||
private:
|
||||
bool ready;
|
||||
bool terminated;
|
||||
std::shared_ptr<ActorBase> actor;
|
||||
};
|
||||
|
||||
class SingleThread : public ActorPolicy {
|
||||
public:
|
||||
SingleThread();
|
||||
virtual ~SingleThread();
|
||||
|
||||
protected:
|
||||
virtual void Terminate(const ActorBase *actor);
|
||||
virtual int EnqueMessage(std::unique_ptr<MessageBase> &msg);
|
||||
virtual std::list<std::unique_ptr<MessageBase>> *GetMsgs();
|
||||
virtual void Notify();
|
||||
|
||||
private:
|
||||
std::condition_variable conditionVar;
|
||||
};
|
||||
|
||||
}; // end of namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORPOLICYINTERFACE_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORPOLICYINTERFACE_H
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class ActorPolicy {
|
||||
public:
|
||||
ActorPolicy() : mailbox1(), mailbox2() {
|
||||
enqueMailbox = &mailbox1;
|
||||
dequeMailbox = &mailbox2;
|
||||
msgCount = 0;
|
||||
start = false;
|
||||
};
|
||||
virtual ~ActorPolicy(){};
|
||||
inline void SwapMailbox() {
|
||||
std::list<std::unique_ptr<MessageBase>> *temp;
|
||||
temp = enqueMailbox;
|
||||
enqueMailbox = dequeMailbox;
|
||||
dequeMailbox = temp;
|
||||
msgCount = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetRunningStatus(bool startRun);
|
||||
virtual void Terminate(const ActorBase *actor) = 0;
|
||||
virtual int EnqueMessage(std::unique_ptr<MessageBase> &msg) = 0;
|
||||
virtual std::list<std::unique_ptr<MessageBase>> *GetMsgs() = 0;
|
||||
virtual void Notify() = 0;
|
||||
|
||||
std::list<std::unique_ptr<MessageBase>> *enqueMailbox;
|
||||
std::list<std::unique_ptr<MessageBase>> *dequeMailbox;
|
||||
|
||||
int msgCount;
|
||||
bool start;
|
||||
std::mutex mailboxLock;
|
||||
|
||||
private:
|
||||
friend class ActorBase;
|
||||
|
||||
std::list<std::unique_ptr<MessageBase>> mailbox1;
|
||||
std::list<std::unique_ptr<MessageBase>> mailbox2;
|
||||
};
|
||||
|
||||
}; // end of namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "actor/actorthread.h"
|
||||
#include <atomic>
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
constexpr int MAXTHREADNAMELEN = 12;
|
||||
ActorThread::ActorThread() : readyActors(), workers() {
|
||||
readyActors.clear();
|
||||
workers.clear();
|
||||
|
||||
char *envThreadName = getenv("LITEBUS_THREAD_NAME");
|
||||
if (envThreadName != nullptr) {
|
||||
threadName = envThreadName;
|
||||
if (threadName.size() > MAXTHREADNAMELEN) {
|
||||
threadName.resize(MAXTHREADNAMELEN);
|
||||
}
|
||||
} else {
|
||||
threadName = "HARES_LB_ACT";
|
||||
}
|
||||
}
|
||||
|
||||
ActorThread::~ActorThread() {}
|
||||
void ActorThread::AddThread(int threadCount) {
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
std::unique_ptr<std::thread> worker(new (std::nothrow) std::thread(&ActorThread::Run, this));
|
||||
BUS_OOM_EXIT(worker);
|
||||
workers.push_back(std::move(worker));
|
||||
}
|
||||
}
|
||||
void ActorThread::Finalize() {
|
||||
MS_LOG(INFO) << "Actor's threads are exiting.";
|
||||
// terminate all thread; enqueue nullptr actor to terminate;
|
||||
std::shared_ptr<ActorBase> exitActor(nullptr);
|
||||
for (auto it = workers.begin(); it != workers.end(); ++it) {
|
||||
EnqueReadyActor(exitActor);
|
||||
}
|
||||
// wait all thread to exit
|
||||
for (auto it = workers.begin(); it != workers.end(); ++it) {
|
||||
std::unique_ptr<std::thread> &worker = *it;
|
||||
if (worker->joinable()) {
|
||||
worker->join();
|
||||
}
|
||||
}
|
||||
workers.clear();
|
||||
MS_LOG(INFO) << "Actor's threads finish exiting.";
|
||||
}
|
||||
|
||||
void ActorThread::DequeReadyActor(std::shared_ptr<ActorBase> &actor) {
|
||||
std::unique_lock<std::mutex> lock(readyActorMutex);
|
||||
conditionVar.wait(lock, [this] { return (this->readyActors.size() > 0); });
|
||||
actor = readyActors.front();
|
||||
readyActors.pop_front();
|
||||
}
|
||||
|
||||
void ActorThread::EnqueReadyActor(const std::shared_ptr<ActorBase> &actor) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(readyActorMutex);
|
||||
readyActors.push_back(actor);
|
||||
}
|
||||
conditionVar.notify_one();
|
||||
}
|
||||
|
||||
void ActorThread::Run() {
|
||||
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12
|
||||
static std::atomic<int> actorCount(1);
|
||||
int ret = pthread_setname_np(pthread_self(), (threadName + std::to_string(actorCount.fetch_add(1))).c_str());
|
||||
if (0 != ret) {
|
||||
MS_LOG(INFO) << "set pthread name fail]ret:" << ret;
|
||||
} else {
|
||||
MS_LOG(INFO) << "set pthread name success]threadID:" << pthread_self();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool terminate = false;
|
||||
do {
|
||||
std::shared_ptr<ActorBase> actor;
|
||||
DequeReadyActor(actor);
|
||||
if (actor != nullptr) {
|
||||
actor->Run();
|
||||
} else {
|
||||
terminate = true;
|
||||
MS_LOG(DEBUG) << "Actor this Threads have finished exiting.";
|
||||
}
|
||||
|
||||
} while (!terminate);
|
||||
}
|
||||
|
||||
}; // end of namespace mindspore
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORTHREAD_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_ACTORTHREAD_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <list>
|
||||
#include <thread>
|
||||
|
||||
#include "actor/actor.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class ActorThread {
|
||||
public:
|
||||
ActorThread();
|
||||
~ActorThread();
|
||||
void Finalize();
|
||||
void AddThread(int threadCount);
|
||||
void EnqueReadyActor(const std::shared_ptr<ActorBase> &actor);
|
||||
|
||||
private:
|
||||
void Run();
|
||||
void DequeReadyActor(std::shared_ptr<ActorBase> &actor);
|
||||
|
||||
std::list<std::shared_ptr<ActorBase>> readyActors;
|
||||
std::mutex readyActorMutex;
|
||||
std::condition_variable conditionVar;
|
||||
|
||||
std::list<std::unique_ptr<std::thread>> workers;
|
||||
std::string threadName;
|
||||
};
|
||||
|
||||
}; // end of namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "actor/aid.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
constexpr int PORTMINNUMBER = 0;
|
||||
constexpr int PORTMAXNUMBER = 65535;
|
||||
constexpr int PROCOLLEN = 3; // strlen("://");
|
||||
|
||||
void AID::SetUnfixUrl() {
|
||||
size_t index = url.find("://");
|
||||
if (index != std::string::npos) {
|
||||
if (url.substr(0, index) == BUS_TCP) {
|
||||
url = url.substr(index + PROCOLLEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AID::AID(const char *tmpName) {
|
||||
std::string sName = tmpName;
|
||||
size_t index = sName.find("@");
|
||||
if (index == std::string::npos) {
|
||||
name = sName;
|
||||
url = "";
|
||||
} else {
|
||||
name = sName.substr(0, index);
|
||||
url = sName.substr(index + 1);
|
||||
SetUnfixUrl();
|
||||
}
|
||||
}
|
||||
|
||||
AID::AID(const std::string &tmpName) {
|
||||
size_t index = tmpName.find("@");
|
||||
if (index == std::string::npos) {
|
||||
name = tmpName;
|
||||
url = "";
|
||||
} else {
|
||||
name = tmpName.substr(0, index);
|
||||
url = tmpName.substr(index + 1);
|
||||
SetUnfixUrl();
|
||||
}
|
||||
}
|
||||
|
||||
bool AID::OK() const {
|
||||
std::string proto = GetProtocol();
|
||||
#ifdef UDP_ENABLED
|
||||
bool protoOK = (proto == BUS_TCP) || (proto == BUS_UDP);
|
||||
#else
|
||||
bool protoOK = (proto == BUS_TCP);
|
||||
#endif
|
||||
int port = GetPort();
|
||||
bool portOK = port > PORTMINNUMBER && port < PORTMAXNUMBER;
|
||||
return protoOK && portOK && name != "";
|
||||
}
|
||||
AID &AID::operator=(const AID &id) {
|
||||
if (&id != this) {
|
||||
name = id.name;
|
||||
url = id.url;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void AID::SetProtocol(const std::string &protocol) {
|
||||
size_t index = url.find("://");
|
||||
if (index != std::string::npos) {
|
||||
if (protocol == BUS_TCP) {
|
||||
url = url.substr(index + PROCOLLEN);
|
||||
} else {
|
||||
url = protocol + url.substr(index);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (protocol == BUS_TCP) {
|
||||
// url = url;
|
||||
} else {
|
||||
url = protocol + "://" + url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string AID::GetProtocol() const {
|
||||
size_t index = url.find("://");
|
||||
if (index != std::string::npos) {
|
||||
return url.substr(0, index);
|
||||
} else {
|
||||
return "tcp";
|
||||
}
|
||||
}
|
||||
|
||||
std::string AID::GetIp() const {
|
||||
size_t index1 = url.find("://");
|
||||
if (index1 == std::string::npos) {
|
||||
index1 = 0;
|
||||
} else {
|
||||
index1 = index1 + PROCOLLEN;
|
||||
}
|
||||
size_t index2 = url.rfind(':');
|
||||
if ((index2 == std::string::npos) || (index2 < index1)) {
|
||||
MS_LOG(INFO) << "wrong url:%s,u=" << url.c_str();
|
||||
return url;
|
||||
} else {
|
||||
return url.substr(index1, index2 - index1);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AID::GetPort() const {
|
||||
size_t index = url.rfind(':');
|
||||
return (uint16_t)std::stoul(url.substr(index + 1));
|
||||
}
|
||||
|
||||
}; // end of namespace mindspore
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_IOMGR_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_IOMGR_H
|
||||
#include <memory>
|
||||
#include "actor/aid.h"
|
||||
|
||||
#include "actor/msg.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class AID;
|
||||
class MessageBase;
|
||||
|
||||
// Server socket listen backlog.
|
||||
static const int SOCKET_LISTEN_BACKLOG = 2048;
|
||||
|
||||
static const int SOCKET_KEEPALIVE = 1;
|
||||
|
||||
// Send first probe after `interval' seconds.
|
||||
static const int SOCKET_KEEPIDLE = 600;
|
||||
|
||||
// Send next probes after the specified interval.
|
||||
static const int SOCKET_KEEPINTERVAL = 5;
|
||||
|
||||
// Consider the socket in error state after we send three ACK
|
||||
// probes without getting a reply.
|
||||
static const int SOCKET_KEEPCOUNT = 3;
|
||||
|
||||
static const std::string BUS_MAGICID = "BUS0";
|
||||
|
||||
static const std::string URL_PROTOCOL_IP_SEPARATOR = "://";
|
||||
|
||||
static const std::string URL_IP_PORT_SEPARATOR = ":";
|
||||
|
||||
static const std::string UDP_EVLOOP_THREADNAME = "HARES_LB_Udp";
|
||||
|
||||
static const std::string TCP_RECV_EVLOOP_THREADNAME = "HARES_LB_TcpR";
|
||||
static const std::string TCP_SEND_EVLOOP_THREADNAME = "HARES_LB_TcpS";
|
||||
|
||||
static const std::string HTTP_CLIENT_EVLOOP_THREADNAME = "HARES_LB_Htp";
|
||||
|
||||
class IOMgr {
|
||||
public:
|
||||
using MsgHandler = void (*)(std::unique_ptr<MessageBase> &&msg);
|
||||
/**
|
||||
* remoteLink and isExactNotRemote are flags to tell us which link should be used. There are several cases:
|
||||
* 1. remoteLink is false and isExactNotRemote is false : callers can reuse remote link when threr are no links
|
||||
* created before.
|
||||
* 2. remoteLink is true and isExactNotRemote is false : callers can only use remote link
|
||||
* 3. remoteLink is true and isExactNotRemote is true : as the same as case 2
|
||||
* 4. remoteLink is false and isExactNotRemote is true : callers can't reuse remote link. if no link,
|
||||
* we will create a new one for callers.
|
||||
*/
|
||||
virtual int Send(std::unique_ptr<MessageBase> &&msg, bool remoteLink = false, bool isExactNotRemote = false) = 0;
|
||||
virtual void Link(const AID &sAid, const AID &dAid) = 0;
|
||||
// close the socket,and send exitedEvent to all linkers.
|
||||
virtual void UnLink(const AID &dAid) = 0;
|
||||
virtual void Reconnect(const AID &sAid, const AID &dAid) = 0;
|
||||
virtual void RegisterMsgHandle(MsgHandler handle) = 0;
|
||||
virtual bool Init() = 0; // once
|
||||
virtual void Finish() = 0; // once
|
||||
virtual bool StartIOServer(const std::string &url, const std::string &advertiseUrl) = 0; // multicalledable
|
||||
virtual uint64_t GetOutBufSize() = 0;
|
||||
virtual uint64_t GetInBufSize() = 0;
|
||||
virtual void CollectMetrics() = 0;
|
||||
virtual int AddRuleUdp(std::string peer, int recordNum) = 0;
|
||||
virtual void DelRuleUdp(std::string peer, bool outputLog) = 0;
|
||||
virtual void LinkRecycleCheck(int recyclePeroid) = 0;
|
||||
IOMgr() {}
|
||||
virtual ~IOMgr() {}
|
||||
};
|
||||
|
||||
}; // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <actor/sysmgr_actor.h>
|
||||
#include "actor/actormgr.h"
|
||||
#include "actor/iomgr.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
Duration SysMgrActor::linkRecycleDuration = 10000;
|
||||
|
||||
void MetricsMessage::PrintMetrics() {
|
||||
// print sendMetrics by default, in the future we can add more metrics format
|
||||
std::ostringstream out;
|
||||
|
||||
while (!intTypeMetrics.empty()) {
|
||||
out << intTypeMetrics.front() << "-";
|
||||
intTypeMetrics.pop();
|
||||
}
|
||||
|
||||
out << "|";
|
||||
|
||||
while (!stringTypeMetrics.empty()) {
|
||||
std::string stringMetric = stringTypeMetrics.front();
|
||||
if (stringMetric.empty()) {
|
||||
out << "null"
|
||||
<< "-";
|
||||
} else {
|
||||
out << stringMetric << "-";
|
||||
}
|
||||
|
||||
stringTypeMetrics.pop();
|
||||
}
|
||||
|
||||
MS_LOG(INFO) << "[format:fd-err-sum-size|to-okmsg-failmsg], value:" << out.str().c_str();
|
||||
}
|
||||
|
||||
void SysMgrActor::SendMetricsDurationCallback() {
|
||||
std::string protocol = "tcp";
|
||||
std::shared_ptr<mindspore::IOMgr> ioMgrRef = ActorMgr::GetIOMgrRef(protocol);
|
||||
if (ioMgrRef == nullptr) {
|
||||
MS_LOG(INFO) << "tcp protocol is not exist.";
|
||||
} else {
|
||||
ioMgrRef->CollectMetrics();
|
||||
}
|
||||
|
||||
(void)AsyncAfter(printSendMetricsDuration, GetAID(), &SysMgrActor::SendMetricsDurationCallback);
|
||||
}
|
||||
|
||||
void SysMgrActor::HandleSendMetricsCallback(const AID &from, std::unique_ptr<MetricsMessage> message) {
|
||||
if (message == nullptr) {
|
||||
MS_LOG(WARNING) << "Can't transform to MetricsMessage.";
|
||||
return;
|
||||
}
|
||||
message->PrintMetrics();
|
||||
return;
|
||||
}
|
||||
|
||||
void SysMgrActor::LinkRecycleDurationCallback() {
|
||||
std::string protocol = "tcp";
|
||||
std::shared_ptr<mindspore::IOMgr> ioMgrRef = ActorMgr::GetIOMgrRef(protocol);
|
||||
if (ioMgrRef == nullptr) {
|
||||
MS_LOG(INFO) << "tcp protocol is not exist.";
|
||||
} else {
|
||||
ioMgrRef->LinkRecycleCheck(linkRecyclePeriod);
|
||||
}
|
||||
|
||||
(void)AsyncAfter(linkRecycleDuration, GetAID(), &SysMgrActor::LinkRecycleDurationCallback);
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 MINDSPORE_CORE_MINDRT_SRC_ACTOR_SYSMGR_ACTOR_H
|
||||
#define MINDSPORE_CORE_MINDRT_SRC_ACTOR_SYSMGR_ACTOR_H
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "async/async.h"
|
||||
#include "async/asyncafter.h"
|
||||
#include "actor/actorapp.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
const std::string SYSMGR_ACTOR_NAME = "SysMgrActor";
|
||||
const std::string METRICS_SEND_MSGNAME = "SendMetrics";
|
||||
const int LINK_RECYCLE_PERIOD_MIN = 20;
|
||||
const int LINK_RECYCLE_PERIOD_MAX = 360;
|
||||
|
||||
using IntTypeMetrics = std::queue<int>;
|
||||
using StringTypeMetrics = std::queue<std::string>;
|
||||
|
||||
class MetricsMessage : public MessageBase {
|
||||
public:
|
||||
explicit MetricsMessage(const std::string &tfrom, const std::string &tTo, const std::string &tName,
|
||||
const IntTypeMetrics &tInts = IntTypeMetrics(),
|
||||
const StringTypeMetrics &tStrings = StringTypeMetrics())
|
||||
: MessageBase(tfrom, tTo, tName), intTypeMetrics(tInts), stringTypeMetrics(tStrings) {}
|
||||
|
||||
~MetricsMessage() override {}
|
||||
|
||||
void PrintMetrics();
|
||||
|
||||
private:
|
||||
IntTypeMetrics intTypeMetrics;
|
||||
StringTypeMetrics stringTypeMetrics;
|
||||
};
|
||||
|
||||
class SysMgrActor : public mindspore::AppActor {
|
||||
public:
|
||||
explicit SysMgrActor(const std::string &name, const Duration &duration)
|
||||
: mindspore::AppActor(name), printSendMetricsDuration(duration) {
|
||||
linkRecyclePeriod = 0;
|
||||
}
|
||||
|
||||
~SysMgrActor() override {}
|
||||
|
||||
protected:
|
||||
virtual void Init() override {
|
||||
MS_LOG(INFO) << "Initiaize SysMgrActor";
|
||||
// register receive handle
|
||||
Receive("SendMetrics", &SysMgrActor::HandleSendMetricsCallback);
|
||||
|
||||
// start sys manager timers
|
||||
(void)AsyncAfter(printSendMetricsDuration, GetAID(), &SysMgrActor::SendMetricsDurationCallback);
|
||||
|
||||
char *linkRecycleEnv = getenv("LITEBUS_LINK_RECYCLE_PERIOD");
|
||||
if (linkRecycleEnv != nullptr) {
|
||||
int period = 0;
|
||||
period = std::stoi(linkRecycleEnv);
|
||||
if (period >= LINK_RECYCLE_PERIOD_MIN && period <= LINK_RECYCLE_PERIOD_MAX) {
|
||||
MS_LOG(INFO) << "link recycle set:" << period;
|
||||
linkRecyclePeriod = period;
|
||||
(void)AsyncAfter(linkRecycleDuration, GetAID(), &SysMgrActor::LinkRecycleDurationCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void SendMetricsDurationCallback();
|
||||
void HandleSendMetricsCallback(const AID &from, std::unique_ptr<MetricsMessage> message);
|
||||
void LinkRecycleDurationCallback();
|
||||
Duration printSendMetricsDuration;
|
||||
static Duration linkRecycleDuration;
|
||||
int linkRecyclePeriod;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
target_sources(litebus_obj PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/async.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/future.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/uuid_base.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/uuid_generator.cc
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/flag_parser_impl.cpp
|
||||
)
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "async/async.h"
|
||||
#include "actor/actormgr.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
class MessageAsync : public MessageBase {
|
||||
public:
|
||||
explicit MessageAsync(std::unique_ptr<MessageHandler> h)
|
||||
: MessageBase("Async", Type::KASYNC), handler(std::move(h)) {}
|
||||
|
||||
~MessageAsync() override {}
|
||||
|
||||
void Run(ActorBase *actor) override { (*handler)(actor); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<MessageHandler> handler;
|
||||
};
|
||||
|
||||
void Async(const AID &aid, std::unique_ptr<std::function<void(ActorBase *)>> handler) {
|
||||
std::unique_ptr<MessageAsync> msg(new (std::nothrow) MessageAsync(std::move(handler)));
|
||||
BUS_OOM_EXIT(msg);
|
||||
(void)ActorMgr::GetActorMgrRef()->Send(aid, std::move(msg));
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "async/future.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace internal {
|
||||
|
||||
void Waitf(const AID &aid) {
|
||||
mindspore::Terminate(aid);
|
||||
MS_LOG(WARNING) << "WaitFor is timeout.";
|
||||
}
|
||||
|
||||
void Wait(const AID &aid, const mindspore::Timer &timer) {
|
||||
mindspore::TimerTools::Cancel(timer);
|
||||
mindspore::Terminate(aid);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <random>
|
||||
#include "async/uuid_base.h"
|
||||
#include <atomic>
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace uuids {
|
||||
|
||||
constexpr int DASH_POS0 = 4;
|
||||
constexpr int DASH_POS1 = 6;
|
||||
constexpr int DASH_POS2 = 8;
|
||||
constexpr int DASH_POS3 = 10;
|
||||
constexpr int SHIFT_BIT = 4;
|
||||
|
||||
const uint8_t *uuid::BeginAddress() const { return uuidData; }
|
||||
|
||||
const uint8_t *uuid::EndAddress() const { return uuidData + UUID_SIZE; }
|
||||
|
||||
std::size_t uuid::Size() { return UUID_SIZE; }
|
||||
|
||||
std::string uuid::ToBytes(const uuid &u) {
|
||||
BUS_ASSERT(sizeof(u) == UUID_SIZE);
|
||||
return std::string(reinterpret_cast<const char *>(u.uuidData), sizeof(u.uuidData));
|
||||
}
|
||||
|
||||
Option<uuid> uuid::FromBytes(const std::string &s) {
|
||||
if (s.size() != UUID_SIZE) {
|
||||
return None();
|
||||
}
|
||||
uuid u;
|
||||
memcpy(&u.uuidData, s.data(), s.size());
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
Option<unsigned char> uuid::GetValue(char c) {
|
||||
static char const digitsBegin[] = "0123456789abcdefABCDEF";
|
||||
static const size_t digitsLen = (sizeof(digitsBegin) / sizeof(char)) - 1;
|
||||
static const char *const digitsEnd = digitsBegin + digitsLen;
|
||||
static unsigned char const values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15};
|
||||
size_t pos = std::find(digitsBegin, digitsEnd, c) - digitsBegin;
|
||||
if (pos >= digitsLen) {
|
||||
MS_LOG(ERROR) << "invalid char";
|
||||
return None();
|
||||
}
|
||||
return values[pos];
|
||||
}
|
||||
|
||||
Option<uuid> uuid::FromString(const std::string &s) {
|
||||
auto sBegin = s.begin();
|
||||
if (sBegin == s.end()) {
|
||||
return None();
|
||||
}
|
||||
auto c = *sBegin;
|
||||
bool hasOpenBrace = (c == '{');
|
||||
bool hasDashes = false;
|
||||
if (hasOpenBrace) {
|
||||
++sBegin;
|
||||
}
|
||||
uuid u;
|
||||
for (size_t i = 0; sBegin != s.end(); ++i) {
|
||||
c = *(sBegin++);
|
||||
if ((i == DASH_POS0) && (c == '-')) {
|
||||
hasDashes = true;
|
||||
c = *(sBegin++);
|
||||
} else if ((i == DASH_POS1 || i == DASH_POS2 || i == DASH_POS3) && (hasDashes == true)) {
|
||||
if (c == '-' && sBegin != s.end()) {
|
||||
c = *(sBegin++);
|
||||
} else {
|
||||
MS_LOG(ERROR) << "str invalid";
|
||||
return None();
|
||||
}
|
||||
}
|
||||
Option<unsigned char> oc1 = GetValue(c);
|
||||
if (oc1.IsNone()) {
|
||||
return None();
|
||||
}
|
||||
u.uuidData[i] = oc1.Get();
|
||||
if (sBegin != s.end()) {
|
||||
c = *(sBegin++);
|
||||
}
|
||||
u.uuidData[i] <<= SHIFT_BIT;
|
||||
Option<unsigned char> oc2 = GetValue(c);
|
||||
if (oc2.IsNone()) {
|
||||
return None();
|
||||
}
|
||||
u.uuidData[i] |= oc2.Get();
|
||||
}
|
||||
if ((hasOpenBrace && (c != '}')) || (sBegin != s.end())) {
|
||||
MS_LOG(ERROR) << "No } end or leng invalid";
|
||||
return None();
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
// To check whether uuid looks like 0000000-000-000-000-000000000000000
|
||||
bool uuid::IsNilUUID() const {
|
||||
for (std::size_t i = 0; i < Size(); i++) {
|
||||
if (uuidData[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t *uuid::Get() const { return uuidData; }
|
||||
|
||||
uint8_t *uuid::BeginAddress() { return uuidData; }
|
||||
|
||||
uint8_t *uuid::EndAddress() { return uuidData + UUID_SIZE; }
|
||||
|
||||
uuid RandomBasedGenerator::GenerateRandomUuid() {
|
||||
const int VARIANT_BIT_OFFSET = 8;
|
||||
const int VERSION_BIT_OFFSET = 6;
|
||||
const int RIGHT_SHIFT_BITS = 8;
|
||||
uuid tmpUUID;
|
||||
|
||||
// This is used to generate a random number as a random seed
|
||||
std::random_device rd;
|
||||
|
||||
// Mersenne Twister algorithm, as a generator engine,
|
||||
// which is used to generate a random number
|
||||
std::mt19937 gen(rd());
|
||||
|
||||
// We use uniform distribution
|
||||
std::uniform_int_distribution<unsigned long> distribution((std::numeric_limits<unsigned long>::min)(),
|
||||
(std::numeric_limits<unsigned long>::max)());
|
||||
|
||||
unsigned long randomValue = distribution(gen);
|
||||
|
||||
unsigned int i = 0;
|
||||
for (uint8_t *it = tmpUUID.BeginAddress(); it != tmpUUID.EndAddress(); ++it, ++i) {
|
||||
if (i == sizeof(unsigned long)) {
|
||||
randomValue = distribution(gen);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
*it = static_cast<uint8_t>((randomValue >> (i * RIGHT_SHIFT_BITS)) & 0xFF);
|
||||
}
|
||||
|
||||
// use atomic ++ to replace random
|
||||
static std::atomic<unsigned long> ul(1);
|
||||
unsigned long lCount = ul.fetch_add(1);
|
||||
unsigned long offSet = distribution(gen) % RIGHT_SHIFT_BITS;
|
||||
auto ret = memcpy(tmpUUID.BeginAddress() + offSet, &lCount, sizeof(lCount));
|
||||
if (ret != 0) {
|
||||
MS_LOG(ERROR) << "memcpy_s error.";
|
||||
BUS_OOM_EXIT(tmpUUID.BeginAddress());
|
||||
}
|
||||
|
||||
// set the variant
|
||||
*(tmpUUID.BeginAddress() + VARIANT_BIT_OFFSET) &= 0xBF;
|
||||
*(tmpUUID.BeginAddress() + VARIANT_BIT_OFFSET) |= 0x80;
|
||||
|
||||
// set the uuid generation version
|
||||
*(tmpUUID.BeginAddress() + VERSION_BIT_OFFSET) &= 0x4F;
|
||||
*(tmpUUID.BeginAddress() + VERSION_BIT_OFFSET) |= 0x40;
|
||||
|
||||
return tmpUUID;
|
||||
}
|
||||
|
||||
} // namespace uuids
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "async/uuid_generator.h"
|
||||
#include <atomic>
|
||||
#include <climits>
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
namespace uuid_generator {
|
||||
UUID UUID::GetRandomUUID() { return UUID(mindspore::uuids::RandomBasedGenerator::GenerateRandomUuid()); }
|
||||
|
||||
std::string UUID::ToString() {
|
||||
std::ostringstream ret;
|
||||
ret << *this;
|
||||
return ret.str();
|
||||
}
|
||||
} // namespace uuid_generator
|
||||
|
||||
namespace localid_generator {
|
||||
int GenLocalActorId() {
|
||||
static std::atomic<int> localActorId(0);
|
||||
return localActorId.fetch_add(1);
|
||||
}
|
||||
|
||||
#ifdef HTTP_ENABLED
|
||||
// not support muti-thread
|
||||
int GenHttpClientConnId() {
|
||||
static int httpClientConnId = 1;
|
||||
if (httpClientConnId == INT_MAX) {
|
||||
httpClientConnId = 1;
|
||||
}
|
||||
return httpClientConnId++;
|
||||
}
|
||||
|
||||
// not support muti-thread
|
||||
int GenHttpServerConnId() {
|
||||
static int httpServerConnId = 1;
|
||||
if (httpServerConnId == INT_MAX) {
|
||||
httpServerConnId = 1;
|
||||
}
|
||||
return httpServerConnId++;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace localid_generator
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,3 @@
|
|||
target_sources(litebus_obj PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/evloop.cc
|
||||
)
|
|
@ -0,0 +1,387 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <atomic>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "actor/buslog.h"
|
||||
#include "evloop/evloop.h"
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
int EventLoopRun(EvLoop *evloop, int timeout) {
|
||||
int nevent = 0;
|
||||
struct epoll_event *events = nullptr;
|
||||
|
||||
(void)sem_post(&evloop->semId);
|
||||
|
||||
size_t size = 1;
|
||||
events = (struct epoll_event *)malloc(size);
|
||||
if (events == nullptr) {
|
||||
MS_LOG(ERROR) << "malloc events fail";
|
||||
return BUS_ERROR;
|
||||
}
|
||||
// 1. dest is valid 2. destsz equals to count and both are valid.
|
||||
// memset_s will always executes successfully.
|
||||
(void)memset(events, 0, size);
|
||||
|
||||
while (!evloop->stopLoop) {
|
||||
/* free deleted event handlers */
|
||||
evloop->EventFreeDelEvents();
|
||||
|
||||
MS_LOG(DEBUG) << "timeout:" << timeout << ",epoll_fd:" << evloop->efd;
|
||||
MS_LOG(DEBUG) << "nevent:" << nevent << ",epoll_fd:" << evloop->efd;
|
||||
if (nevent < 0) {
|
||||
if (errno != EINTR) {
|
||||
MS_LOG(ERROR) << "epoll_wait failed]epoll_fd:" << evloop->efd << ",errno:" << errno;
|
||||
free(events);
|
||||
return BUS_ERROR;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if (nevent > 0) {
|
||||
/* save the epoll modify in "stop" while dispatching handlers */
|
||||
evloop->HandleEvent(events, nevent);
|
||||
} else {
|
||||
MS_LOG(ERROR) << "epoll_wait failed]epoll_fd:" << evloop->efd << ",ret:0,errno:" << errno;
|
||||
evloop->stopLoop = 1;
|
||||
}
|
||||
|
||||
if (evloop->stopLoop) {
|
||||
/* free deleted event handlers */
|
||||
evloop->EventFreeDelEvents();
|
||||
}
|
||||
}
|
||||
evloop->stopLoop = 0;
|
||||
MS_LOG(INFO) << "event epoll loop run end";
|
||||
free(events);
|
||||
return BUS_OK;
|
||||
}
|
||||
|
||||
void *EvloopRun(void *arg) {
|
||||
if (arg == nullptr) {
|
||||
MS_LOG(ERROR) << "arg is null";
|
||||
} else {
|
||||
(void)EventLoopRun((EvLoop *)arg, -1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QueueReadyCallback(int fd, uint32_t events, void *arg) {
|
||||
EvLoop *evloop = (EvLoop *)arg;
|
||||
if (evloop == nullptr) {
|
||||
MS_LOG(ERROR) << "evloop is null]fd:" << fd << ",events:" << events;
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t count;
|
||||
if (read(evloop->queueEventfd, &count, sizeof(count)) == sizeof(count)) {
|
||||
// take out functions from the queue
|
||||
std::queue<std::function<void()>> q;
|
||||
|
||||
evloop->queueMutex.lock();
|
||||
evloop->queue.swap(q);
|
||||
evloop->queueMutex.unlock();
|
||||
|
||||
// invoke functions in the queue
|
||||
while (!q.empty()) {
|
||||
q.front()();
|
||||
q.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EvLoop::CleanUp() {
|
||||
if (queueEventfd != -1) {
|
||||
close(queueEventfd);
|
||||
queueEventfd = -1;
|
||||
}
|
||||
|
||||
if (efd != -1) {
|
||||
close(efd);
|
||||
efd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int EvLoop::AddFuncToEvLoop(std::function<void()> &&func) {
|
||||
// put func to the queue
|
||||
queueMutex.lock();
|
||||
queue.emplace(std::move(func));
|
||||
// return the queque size to send's caller.
|
||||
int result = queue.size();
|
||||
queueMutex.unlock();
|
||||
|
||||
if (result == 1) {
|
||||
// wakeup event loop
|
||||
uint64_t one = 1;
|
||||
if (write(queueEventfd, &one, sizeof(one)) != sizeof(one)) {
|
||||
MS_LOG(WARNING) << "fail to write queueEventfd]fd:" << queueEventfd << ",errno:" << errno;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool EvLoop::Init(const std::string &threadName) {
|
||||
int retval = EventLoopCreate();
|
||||
if (retval != BUS_OK) {
|
||||
return false;
|
||||
}
|
||||
(void)sem_init(&semId, 0, 0);
|
||||
|
||||
if (pthread_create(&loopThread, nullptr, EvloopRun, (void *)this) != 0) {
|
||||
MS_LOG(ERROR) << "pthread_create fail";
|
||||
Finish();
|
||||
return false;
|
||||
}
|
||||
// wait EvloopRun
|
||||
(void)sem_wait(&semId);
|
||||
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12
|
||||
std::string name = threadName;
|
||||
if (name.empty()) {
|
||||
name = "EventLoopThread";
|
||||
}
|
||||
retval = pthread_setname_np(loopThread, name.c_str());
|
||||
if (retval != 0) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "set pthread name fail]%s",
|
||||
"name:%s,retval:%d", name.c_str(), retval);
|
||||
} else {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "set pthread name success]%s",
|
||||
"name:%s,loopThread:%lu", name.c_str(), loopThread);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EvLoop::Finish() {
|
||||
if (loopThread) {
|
||||
void *threadResult = nullptr;
|
||||
StopEventLoop();
|
||||
int ret = pthread_join(loopThread, &threadResult);
|
||||
if (ret != 0) {
|
||||
MS_LOG(INFO) << "pthread_join loopThread fail";
|
||||
}
|
||||
loopThread = 0;
|
||||
}
|
||||
EventLoopDestroy();
|
||||
|
||||
MS_LOG(INFO) << "stop loop succ";
|
||||
}
|
||||
|
||||
EvLoop::~EvLoop() { Finish(); }
|
||||
|
||||
void EvLoop::DeleteEvent(int fd) {
|
||||
auto iter = events.find(fd);
|
||||
if (iter == events.end()) {
|
||||
MS_LOG(DEBUG) << "not found event]fd:" << fd;
|
||||
return;
|
||||
}
|
||||
MS_LOG(DEBUG) << "erase event]fd:%d" << fd;
|
||||
EventData *eventData = iter->second;
|
||||
if (eventData != nullptr) {
|
||||
delete eventData;
|
||||
}
|
||||
events.erase(fd);
|
||||
}
|
||||
|
||||
EventData *EvLoop::FindEvent(int fd) {
|
||||
auto iter = events.find(fd);
|
||||
if (iter == events.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
void EvLoop::AddEvent(EventData *eventData) {
|
||||
if (!eventData) {
|
||||
return;
|
||||
}
|
||||
DeleteEvent(eventData->fd);
|
||||
events.emplace(eventData->fd, eventData);
|
||||
}
|
||||
|
||||
int EvLoop::EventLoopCreate(void) { return BUS_OK; }
|
||||
|
||||
int EvLoop::AddFdEvent(int fd, uint32_t tEvents, EventHandler handler, void *data) { return BUS_OK; }
|
||||
|
||||
int EvLoop::DelFdEvent(int fd) {
|
||||
EventData *tev = nullptr;
|
||||
|
||||
eventsLock.lock();
|
||||
tev = FindEvent(fd);
|
||||
if (tev == nullptr) {
|
||||
eventsLock.unlock();
|
||||
MS_LOG(DEBUG) << "event search fail]fd:" << fd << ",epollfd:" << efd;
|
||||
return BUS_ERROR;
|
||||
}
|
||||
events.erase(tev->fd);
|
||||
|
||||
// Don't delete tev immediately, let's push it into deletedEvents, before next epoll_wait,we will free
|
||||
// all events in deletedEvents.
|
||||
AddDeletedEvents(tev);
|
||||
|
||||
eventsLock.unlock();
|
||||
|
||||
return BUS_OK;
|
||||
}
|
||||
|
||||
int EvLoop::ModifyFdEvent(int fd, uint32_t tEvents) {
|
||||
struct epoll_event ev;
|
||||
EventData *tev = nullptr;
|
||||
|
||||
tev = FindEvent(fd);
|
||||
if (tev == nullptr) {
|
||||
MS_LOG(ERROR) << "event lookup fail]fd:" << fd << ",events:" << tEvents;
|
||||
return BUS_ERROR;
|
||||
}
|
||||
|
||||
// 1. dest is valid 2. destsz equals to count and both are valid.
|
||||
// memset_s will always executes successfully.
|
||||
(void)memset(&ev, 0, sizeof(ev));
|
||||
|
||||
ev.events = tEvents;
|
||||
ev.data.ptr = tev;
|
||||
|
||||
return BUS_OK;
|
||||
}
|
||||
|
||||
void EvLoop::AddDeletedEvents(EventData *eventData) {
|
||||
// caller need check eventData is not nullptr
|
||||
std::list<EventData *> deleteEventList;
|
||||
|
||||
// if fd not found, push eventData into deletedEvents[fd]
|
||||
std::map<int, std::list<EventData *>>::iterator fdIter = deletedEvents.find(eventData->fd);
|
||||
if (fdIter == deletedEvents.end()) {
|
||||
deletedEvents[eventData->fd].push_back(eventData);
|
||||
return;
|
||||
}
|
||||
|
||||
// if fd found, check if same eventData ptr exists
|
||||
deleteEventList = fdIter->second;
|
||||
std::list<EventData *>::iterator eventIter = deleteEventList.begin();
|
||||
bool found = false;
|
||||
while (eventIter != deleteEventList.end()) {
|
||||
if (*eventIter == eventData) {
|
||||
MS_LOG(WARNING) << "fd has been deleted before]fd:" << eventData->fd << ",efd:" << efd;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
++eventIter;
|
||||
}
|
||||
|
||||
// if found same eventData ptr, do nothing
|
||||
if (found) {
|
||||
return;
|
||||
}
|
||||
|
||||
deletedEvents[eventData->fd].push_back(eventData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void EvLoop::EventFreeDelEvents() {
|
||||
std::map<int, std::list<EventData *>>::iterator fdIter = deletedEvents.begin();
|
||||
while (fdIter != deletedEvents.end()) {
|
||||
std::list<EventData *> deleteEventList = fdIter->second;
|
||||
std::list<EventData *>::iterator eventIter = deleteEventList.begin();
|
||||
while (eventIter != deleteEventList.end()) {
|
||||
EventData *deleteEv = *eventIter;
|
||||
delete deleteEv;
|
||||
deleteEv = nullptr;
|
||||
++eventIter;
|
||||
}
|
||||
deletedEvents.erase(fdIter++);
|
||||
}
|
||||
deletedEvents.clear();
|
||||
}
|
||||
|
||||
int EvLoop::FindDeletedEvent(const EventData *tev) {
|
||||
std::map<int, std::list<EventData *>>::iterator fdIter = deletedEvents.find(tev->fd);
|
||||
if (fdIter == deletedEvents.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<EventData *> deleteEventList = fdIter->second;
|
||||
std::list<EventData *>::iterator eventIter = deleteEventList.begin();
|
||||
while (eventIter != deleteEventList.end()) {
|
||||
if (*eventIter == tev) {
|
||||
return 1;
|
||||
}
|
||||
++eventIter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EvLoop::HandleEvent(const struct epoll_event *tEvents, int nevent) {
|
||||
int i;
|
||||
int found;
|
||||
EventData *tev = nullptr;
|
||||
|
||||
for (i = 0; i < nevent; i++) {
|
||||
tev = reinterpret_cast<EventData *>(tEvents[i].data.ptr);
|
||||
if (tev != nullptr) {
|
||||
found = FindDeletedEvent(tev);
|
||||
if (found) {
|
||||
MS_LOG(WARNING) << "fd has been deleted from epoll]fd:" << tev->fd << ",efd:" << efd;
|
||||
continue;
|
||||
}
|
||||
|
||||
tev->handler(tev->fd, tEvents[i].events, tev->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EvLoop::StopEventLoop() {
|
||||
if (stopLoop == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
stopLoop = 1;
|
||||
|
||||
uint64_t one = 1;
|
||||
if (write(queueEventfd, &one, sizeof(one)) != sizeof(one)) {
|
||||
MS_LOG(WARNING) << "fail to write queueEventfd]fd:" << queueEventfd << ",errno:" << errno;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void EvLoop::EventLoopDestroy() {
|
||||
/* free deleted event handlers */
|
||||
EventFreeDelEvents();
|
||||
if (efd > 0) {
|
||||
if (queueEventfd > 0) {
|
||||
(void)DelFdEvent(queueEventfd);
|
||||
close(queueEventfd);
|
||||
queueEventfd = -1;
|
||||
}
|
||||
|
||||
close(efd);
|
||||
efd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 __LITEBUS_EVLOOP_H__
|
||||
#define __LITEBUS_EVLOOP_H__
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <sys/eventfd.h>
|
||||
#include <semaphore.h>
|
||||
#include "timer/duration.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
/*
|
||||
* max epoll set size
|
||||
*/
|
||||
constexpr auto EPOLL_SIZE = 4096;
|
||||
|
||||
/*
|
||||
* epoll event max size
|
||||
*/
|
||||
constexpr auto EPOLL_EVENTS_SIZE = 64;
|
||||
|
||||
typedef void (*EventHandler)(int fd, uint32_t events, void *data);
|
||||
|
||||
typedef struct EventData {
|
||||
EventHandler handler;
|
||||
void *data;
|
||||
int fd;
|
||||
|
||||
} EventData;
|
||||
|
||||
class EvLoop {
|
||||
public:
|
||||
EvLoop() {
|
||||
efd = -1;
|
||||
stopLoop = 0;
|
||||
queueEventfd = -1;
|
||||
loopThread = 0;
|
||||
};
|
||||
EvLoop(const EvLoop &) = delete;
|
||||
EvLoop &operator=(const EvLoop &) = delete;
|
||||
|
||||
bool Init(const std::string &threadName);
|
||||
|
||||
int AddFuncToEvLoop(std::function<void()> &&func);
|
||||
|
||||
int AddFdEvent(int fd, uint32_t events, EventHandler handler, void *data);
|
||||
int ModifyFdEvent(int fd, uint32_t events);
|
||||
int DelFdEvent(int fd);
|
||||
void Finish();
|
||||
|
||||
~EvLoop();
|
||||
|
||||
int EventLoopCreate(void);
|
||||
void StopEventLoop();
|
||||
|
||||
void EventLoopDestroy();
|
||||
|
||||
void EventFreeDelEvents();
|
||||
void AddDeletedEvents(EventData *eventData);
|
||||
int FindDeletedEvent(const EventData *tev);
|
||||
|
||||
void HandleEvent(const struct epoll_event *events, int nevent);
|
||||
|
||||
void DeleteEvent(int fd);
|
||||
EventData *FindEvent(int fd);
|
||||
void AddEvent(EventData *eventData);
|
||||
void CleanUp();
|
||||
|
||||
int efd;
|
||||
int stopLoop;
|
||||
std::mutex loopMutex;
|
||||
sem_t semId;
|
||||
pthread_t loopThread;
|
||||
int queueEventfd;
|
||||
std::mutex queueMutex;
|
||||
std::queue<std::function<void()>> queue;
|
||||
|
||||
std::mutex eventsLock;
|
||||
// fd,EventData
|
||||
std::map<int, EventData *> events;
|
||||
|
||||
// Just to be safe, let's use a list to preserve deleted events rather than a map. Because the caller may
|
||||
// delete events on the same fd twice in once epoll_wait
|
||||
std::map<int, std::list<EventData *>> deletedEvents;
|
||||
};
|
||||
|
||||
} // namespace mindspore
|
||||
|
||||
#endif
|
|
@ -0,0 +1,232 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <cstdlib>
|
||||
|
||||
#include "mindrt/src/actor/sysmgr_actor.h"
|
||||
#include "mindrt/src/actor/actormgr.h"
|
||||
#include "mindrt/src/actor/iomgr.h"
|
||||
|
||||
//#include "utils/os_utils.hpp"
|
||||
|
||||
#include "litebus.hpp"
|
||||
#include "timer/timertools.h"
|
||||
#include "litebus.h"
|
||||
|
||||
extern "C" {
|
||||
int LitebusInitializeC(const struct LitebusConfig *config) {
|
||||
if (config == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (config->threadCount == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (config->httpKmsgFlag != 0 && config->httpKmsgFlag != 1) {
|
||||
return -1;
|
||||
}
|
||||
mindspore::SetHttpKmsgFlag(config->httpKmsgFlag);
|
||||
|
||||
return mindspore::Initialize(std::string(config->tcpUrl), std::string(config->tcpUrlAdv), std::string(config->udpUrl),
|
||||
std::string(config->udpUrlAdv), config->threadCount);
|
||||
}
|
||||
|
||||
void LitebusFinalizeC() { mindspore::Finalize(); }
|
||||
}
|
||||
|
||||
constexpr auto LITEBUSTHREADMIN = 3;
|
||||
constexpr auto LITEBUSTHREADMAX = 100;
|
||||
constexpr auto LITEBUSTHREADS = 10;
|
||||
|
||||
constexpr auto SYSMGR_TIMER_DURATION = 600000;
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
namespace local {
|
||||
|
||||
static LitebusAddress *g_litebusAddress = new (std::nothrow) LitebusAddress();
|
||||
static std::atomic_bool g_finalizeLitebusStatus(false);
|
||||
|
||||
} // namespace local
|
||||
|
||||
const LitebusAddress &GetLitebusAddress() {
|
||||
BUS_OOM_EXIT(local::g_litebusAddress);
|
||||
return *local::g_litebusAddress;
|
||||
}
|
||||
|
||||
bool SetServerIo(std::shared_ptr<mindspore::IOMgr> &io, std::string &advertiseUrl, const std::string &protocol,
|
||||
const std::string &url) {
|
||||
#if 0
|
||||
if (protocol == "tcp") {
|
||||
size_t index = advertiseUrl.find("://");
|
||||
if (index != std::string::npos) {
|
||||
advertiseUrl = advertiseUrl.substr(index + URL_PROTOCOL_IP_SEPARATOR.size());
|
||||
}
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "create tcp iomgr. (%s)",
|
||||
"Url=%s,advertiseUrl=%s", url.c_str(), advertiseUrl.c_str());
|
||||
if (local::g_litebusAddress == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"Couldn't allocate memory for LitebusAddress");
|
||||
return false;
|
||||
}
|
||||
local::g_litebusAddress->scheme = protocol;
|
||||
local::g_litebusAddress->ip = AID("test@" + advertiseUrl).GetIp();
|
||||
local::g_litebusAddress->port = AID("test@" + advertiseUrl).GetPort();
|
||||
|
||||
#ifdef HTTP_ENABLED
|
||||
mindspore::HttpIOMgr::EnableHttp();
|
||||
#endif
|
||||
io.reset(new (std::nothrow) mindspore::TCPMgr());
|
||||
if (io == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"Couldn't allocate memory for TCPMgr");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef UDP_ENABLED
|
||||
else if (protocol == "udp") {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "create udp iomgr. (%s)",
|
||||
"Url=%s,advertiseUrl=%s", url.c_str(), advertiseUrl.c_str());
|
||||
|
||||
io.reset(new (std::nothrow) mindspore::UDPMgr());
|
||||
if (io == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"Couldn't allocate memory for UDPMgr");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "unsupported protocol. (%s)",
|
||||
"%s", protocol.c_str());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetThreadCount(int threadCount) {
|
||||
int tmpThreadCount = LITEBUSTHREADS;
|
||||
ActorMgr::GetActorMgrRef()->Initialize(tmpThreadCount);
|
||||
}
|
||||
|
||||
class LiteBusExit {
|
||||
public:
|
||||
LiteBusExit() {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "trace: enter LiteBusExit()---------");
|
||||
}
|
||||
~LiteBusExit() {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "trace: enter ~LiteBusExit()---------");
|
||||
mindspore::Finalize();
|
||||
}
|
||||
};
|
||||
|
||||
int InitializeImp(const std::string &tcpUrl, const std::string &tcpUrlAdv, const std::string &udpUrl,
|
||||
const std::string &udpUrlAdv, int threadCount) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus starts ......");
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!TimerTools::Initialize()) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Failed to initialize timer tools");
|
||||
return BUS_ERROR;
|
||||
}
|
||||
|
||||
// start actor's thread
|
||||
SetThreadCount(threadCount);
|
||||
|
||||
mindspore::Spawn(std::make_shared<SysMgrActor>(SYSMGR_ACTOR_NAME, SYSMGR_TIMER_DURATION));
|
||||
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus has started.");
|
||||
return BUS_OK;
|
||||
}
|
||||
|
||||
int Initialize(const std::string &tcpUrl, const std::string &tcpUrlAdv, const std::string &udpUrl,
|
||||
const std::string &udpUrlAdv, int threadCount) {
|
||||
static std::atomic_bool initLitebusStatus(false);
|
||||
bool inite = false;
|
||||
if (initLitebusStatus.compare_exchange_strong(inite, true) == false) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus has been initialized");
|
||||
return BUS_OK;
|
||||
}
|
||||
|
||||
int result = BUS_OK;
|
||||
result = InitializeImp(tcpUrl, tcpUrlAdv, udpUrl, udpUrlAdv, threadCount);
|
||||
static LiteBusExit busExit;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AID Spawn(ActorReference actor, bool sharedThread, bool start) {
|
||||
if (actor == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "Actor is nullptr.");
|
||||
BUS_EXIT("Actor is nullptr.");
|
||||
}
|
||||
|
||||
if (local::g_finalizeLitebusStatus.load() == true) {
|
||||
return actor->GetAID();
|
||||
} else {
|
||||
return ActorMgr::GetActorMgrRef()->Spawn(actor, sharedThread, start);
|
||||
}
|
||||
}
|
||||
void SetActorStatus(const AID &actor, bool start) { ActorMgr::GetActorMgrRef()->SetActorStatus(actor, start); }
|
||||
|
||||
void Await(const ActorReference &actor) { ActorMgr::GetActorMgrRef()->Wait(actor->GetAID()); }
|
||||
|
||||
void Await(const AID &actor) { ActorMgr::GetActorMgrRef()->Wait(actor); }
|
||||
|
||||
// brief get actor with aid
|
||||
ActorReference GetActor(const AID &actor) { return ActorMgr::GetActorMgrRef()->GetActor(actor); }
|
||||
|
||||
void Terminate(const AID &actor) { ActorMgr::GetActorMgrRef()->Terminate(actor); }
|
||||
|
||||
void TerminateAll() { mindspore::ActorMgr::GetActorMgrRef()->TerminateAll(); }
|
||||
|
||||
void Finalize() {
|
||||
bool inite = false;
|
||||
if (local::g_finalizeLitebusStatus.compare_exchange_strong(inite, true) == false) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus has been Finalized.");
|
||||
return;
|
||||
}
|
||||
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus starts to finalize.");
|
||||
mindspore::ActorMgr::GetActorMgrRef()->Finalize();
|
||||
TimerTools::Finalize();
|
||||
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "litebus has been finalized.");
|
||||
// flush the log in cache to disk before exiting.
|
||||
FlushHLogCache();
|
||||
}
|
||||
|
||||
void SetDelegate(const std::string &delegate) { mindspore::ActorMgr::GetActorMgrRef()->SetDelegate(delegate); }
|
||||
|
||||
static HARES_LOG_PID g_busLogPid = 1;
|
||||
void SetLogPID(HARES_LOG_PID pid) {
|
||||
ICTSBASE_LOG1(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, pid, "Set LiteBus log PID: %u", pid);
|
||||
g_busLogPid = pid;
|
||||
}
|
||||
HARES_LOG_PID GetLogPID() { return g_busLogPid; }
|
||||
|
||||
static int g_httpKmsgEnable = -1;
|
||||
void SetHttpKmsgFlag(int flag) {
|
||||
ICTSBASE_LOG1(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "Set LiteBus http message format:%d", flag);
|
||||
g_httpKmsgEnable = flag;
|
||||
}
|
||||
|
||||
int GetHttpKmsgFlag() { return g_httpKmsgEnable; }
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,5 @@
|
|||
target_sources(litebus_obj PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timer.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timertools.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timewatch.cc
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "timer/timer.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
Timer::Timer() : id(0), t(TimeWatch()), aid(AID()), thunk(&abort) {}
|
||||
|
||||
Timer::~Timer() {}
|
||||
|
||||
bool Timer::operator==(const Timer &that) const { return id == that.id; }
|
||||
|
||||
void Timer::operator()() const { thunk(); }
|
||||
|
||||
TimeWatch Timer::GetTimeWatch() const { return t; }
|
||||
|
||||
AID Timer::GetTimerAID() const { return aid; }
|
||||
|
||||
uint64_t Timer::GetTimerID() const { return id; }
|
||||
|
||||
Timer::Timer(uint64_t timerId, const TimeWatch &timeWatch, const AID &timeAid, const std::function<void()> &handler)
|
||||
: id(timerId), t(timeWatch), aid(timeAid), thunk(handler) {}
|
||||
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,347 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "timer/timertools.h"
|
||||
#include <csignal>
|
||||
#include <ctime>
|
||||
#include <unistd.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include "evloop/evloop.h"
|
||||
|
||||
namespace mindspore {
|
||||
using TimerPoolType = std::map<Duration, std::list<Timer>>;
|
||||
static std::unique_ptr<TimerPoolType> g_timerPool;
|
||||
static std::unique_ptr<EvLoop> g_timerEvLoop;
|
||||
static Duration g_ticks(0);
|
||||
static int g_runTimerFD(-1);
|
||||
static int g_watchTimerFD(-1);
|
||||
static SpinLock g_timersLock;
|
||||
std::atomic_bool TimerTools::g_initStatus(false);
|
||||
constexpr Duration SCAN_TIMERPOOL_DELAY = 30;
|
||||
constexpr Duration WATCH_INTERVAL = 20;
|
||||
constexpr unsigned int TIMER_LOG_INTERVAL = 6;
|
||||
const static std::string TIMER_EVLOOP_THREADNAME = "HARES_LB_TMer";
|
||||
|
||||
namespace timer {
|
||||
void ScanTimerPool(int fd, uint32_t events, void *data);
|
||||
Duration NextTick(const std::map<Duration, std::list<Timer>> &timerPool) {
|
||||
if (!timerPool.empty()) {
|
||||
Duration first = timerPool.begin()->first;
|
||||
return first;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecTimers(const std::list<Timer> &timers) {
|
||||
for (const auto &timer : timers) {
|
||||
timer();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateTimerToLoop(const Duration &delay, const Duration &nextTick) {
|
||||
if (g_runTimerFD == -1) {
|
||||
g_runTimerFD = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (g_runTimerFD >= 0) {
|
||||
int retval = g_timerEvLoop->AddFdEvent(g_runTimerFD, EPOLLIN, ScanTimerPool, nullptr);
|
||||
if (retval != BUS_OK) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "add run timer event fail]%s",
|
||||
"ID:%d", g_runTimerFD);
|
||||
close(g_runTimerFD);
|
||||
g_runTimerFD = -1;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "create run timer fd fail]%s",
|
||||
"ID:%d", g_runTimerFD);
|
||||
g_runTimerFD = -1;
|
||||
return;
|
||||
}
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "create run timer fd success]%s",
|
||||
"ID:%d", g_runTimerFD);
|
||||
}
|
||||
|
||||
struct itimerspec it;
|
||||
it.it_interval.tv_sec = 0;
|
||||
it.it_interval.tv_nsec = 0;
|
||||
it.it_value.tv_sec = delay / SECTOMILLI;
|
||||
it.it_value.tv_nsec = (delay % SECTOMILLI) * MILLITOMICR * MICRTONANO;
|
||||
if (timerfd_settime(g_runTimerFD, 0, &it, nullptr) == -1) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "start run timer fail]%s", "ID:%d",
|
||||
g_runTimerFD);
|
||||
close(g_runTimerFD);
|
||||
g_runTimerFD = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleTick(const std::map<Duration, std::list<Timer>> &timerPool) {
|
||||
Duration nextTick = NextTick(timerPool);
|
||||
|
||||
if (nextTick != 0) {
|
||||
// 'tick' scheduled for an earlier time, not schedule current 'tick'
|
||||
if ((g_ticks == 0) || (nextTick < g_ticks)) {
|
||||
Duration nowTime = TimeWatch::Now();
|
||||
Duration delay = 0;
|
||||
|
||||
if (nextTick > nowTime) {
|
||||
delay = nextTick - nowTime;
|
||||
g_ticks = nextTick;
|
||||
CreateTimerToLoop(delay, nextTick);
|
||||
} else {
|
||||
delay = SCAN_TIMERPOOL_DELAY;
|
||||
g_ticks = delay + nowTime;
|
||||
CreateTimerToLoop(delay, nextTick);
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_DEBUG, PID_LITEBUS_LOG,
|
||||
"run timer immediately {nextTick, now time}= %s ", "{%" PRIu64 ", %" PRIu64 "}", nextTick,
|
||||
nowTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select timeout timers
|
||||
void ScanTimerPool(int fd, uint32_t events, void *data) {
|
||||
std::list<Timer> outTimer;
|
||||
uint64_t count;
|
||||
|
||||
if ((g_runTimerFD != fd) || !(events & EPOLLIN)) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG,
|
||||
"run timer fd or events err {g_runTimerFD, fd, events}= %s ", "{%d, %d, %u}", g_runTimerFD, fd,
|
||||
events);
|
||||
return;
|
||||
}
|
||||
|
||||
if (read(fd, &count, sizeof(uint64_t)) < 0) {
|
||||
return;
|
||||
}
|
||||
g_timersLock.Lock();
|
||||
Duration now = TimeWatch::Now();
|
||||
auto it = g_timerPool->begin();
|
||||
while (it != g_timerPool->end()) {
|
||||
if (it->first > now) {
|
||||
break;
|
||||
}
|
||||
outTimer.splice(outTimer.end(), (*g_timerPool)[it->first]);
|
||||
++it;
|
||||
}
|
||||
// delete timed out timer
|
||||
(void)g_timerPool->erase(g_timerPool->begin(), g_timerPool->upper_bound(now));
|
||||
g_ticks = 0;
|
||||
ScheduleTick(*g_timerPool);
|
||||
g_timersLock.Unlock();
|
||||
|
||||
ExecTimers(outTimer);
|
||||
outTimer.clear();
|
||||
}
|
||||
|
||||
void CheckPassedTimer(int fd, uint32_t events, void *data) {
|
||||
std::list<Timer> passTimer;
|
||||
static unsigned long watchTimes = 0;
|
||||
uint64_t count;
|
||||
|
||||
if ((g_watchTimerFD != fd) || !(events & EPOLLIN)) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG,
|
||||
"check timer fd or events err {g_watchTimerFD, fd, events}= %s ", "{%d, %d, %u}",
|
||||
g_watchTimerFD, fd, events);
|
||||
return;
|
||||
}
|
||||
if (read(fd, &count, sizeof(uint64_t)) < 0) {
|
||||
return;
|
||||
}
|
||||
g_timersLock.Lock();
|
||||
Duration now = TimeWatch::Now();
|
||||
++watchTimes;
|
||||
|
||||
for (auto it = g_timerPool->begin(); it != g_timerPool->end(); ++it) {
|
||||
if (it->first > now) {
|
||||
break;
|
||||
}
|
||||
passTimer.splice(passTimer.end(), (*g_timerPool)[it->first]);
|
||||
}
|
||||
// delete passed timer
|
||||
if (passTimer.size() > 0) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_DEBUG, PID_LITEBUS_LOG,
|
||||
"fire pass timer {pass size, now, g_ticks}= %s ", "{%zd, %" PRIu64 ", %" PRIu64 "}",
|
||||
passTimer.size(), now, g_ticks);
|
||||
}
|
||||
(void)g_timerPool->erase(g_timerPool->begin(), g_timerPool->upper_bound(now));
|
||||
if (g_ticks <= now) {
|
||||
g_ticks = 0;
|
||||
}
|
||||
|
||||
if (g_timerPool->size() > 0) {
|
||||
if ((watchTimes % TIMER_LOG_INTERVAL == 0) && (passTimer.size() > 0) &&
|
||||
(now - g_timerPool->begin()->first > SECTOMILLI)) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG,
|
||||
"timer info {pool size, pass size, now, g_ticks, poolTick, watchTimes}= %s ",
|
||||
"{%zd, %zd, %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %lu}", g_timerPool->size(),
|
||||
passTimer.size(), now, g_ticks, g_timerPool->begin()->first, watchTimes);
|
||||
}
|
||||
}
|
||||
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_DEBUG, PID_LITEBUS_LOG,
|
||||
"timer info {pool size, pass size, now, g_ticks, poolTick, watchTimes}= %s ",
|
||||
"{%zd, %zd, %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %lu}", g_timerPool->size(), passTimer.size(),
|
||||
now, g_ticks, g_timerPool->begin()->first, watchTimes);
|
||||
|
||||
ScheduleTick(*g_timerPool);
|
||||
g_timersLock.Unlock();
|
||||
|
||||
ExecTimers(passTimer);
|
||||
passTimer.clear();
|
||||
}
|
||||
|
||||
bool StartWatchTimer() {
|
||||
// create watch timer
|
||||
g_watchTimerFD = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (g_watchTimerFD >= 0) {
|
||||
int retval = g_timerEvLoop->AddFdEvent(g_watchTimerFD, EPOLLIN, CheckPassedTimer, nullptr);
|
||||
if (retval != BUS_OK) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "add watch timer event fail]%s",
|
||||
"ID:%d", g_watchTimerFD);
|
||||
close(g_watchTimerFD);
|
||||
g_watchTimerFD = -1;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
g_watchTimerFD = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// start watch timer
|
||||
struct itimerspec it;
|
||||
it.it_interval.tv_sec = WATCH_INTERVAL;
|
||||
it.it_interval.tv_nsec = 0;
|
||||
it.it_value.tv_sec = WATCH_INTERVAL;
|
||||
it.it_value.tv_nsec = 0;
|
||||
if (timerfd_settime(g_watchTimerFD, 0, &it, nullptr) == -1) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "start watch timer fail]%s",
|
||||
"ID:%d", g_watchTimerFD);
|
||||
close(g_watchTimerFD);
|
||||
g_watchTimerFD = -1;
|
||||
return false;
|
||||
}
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG,
|
||||
"start watch timer success, {id}= %s ", "{%d}", g_watchTimerFD);
|
||||
return true;
|
||||
}
|
||||
} // namespace timer
|
||||
|
||||
bool TimerTools::Initialize() {
|
||||
bool ret = true;
|
||||
g_timersLock.Lock();
|
||||
|
||||
g_timerPool.reset(new (std::nothrow) TimerPoolType());
|
||||
if (g_timerPool == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "timer pool new failed.");
|
||||
g_timersLock.Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
g_timerEvLoop.reset(new (std::nothrow) EvLoop());
|
||||
if (g_timerEvLoop == nullptr) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "ev new failed.");
|
||||
g_timersLock.Unlock();
|
||||
return false;
|
||||
}
|
||||
bool ok = g_timerEvLoop->Init(TIMER_EVLOOP_THREADNAME);
|
||||
if (!ok) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG, "ev init failed.");
|
||||
g_timerEvLoop = nullptr;
|
||||
g_timersLock.Unlock();
|
||||
return false;
|
||||
}
|
||||
ret = timer::StartWatchTimer();
|
||||
g_timersLock.Unlock();
|
||||
g_initStatus.store(true);
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "Timer init succ.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TimerTools::Finalize() {
|
||||
if (g_initStatus.load() == false) {
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "no need for Timer Finalize.");
|
||||
return;
|
||||
}
|
||||
g_initStatus.store(false);
|
||||
|
||||
ICTSBASE_LOG0(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "Timer Finalize.");
|
||||
g_timersLock.Lock();
|
||||
if (g_runTimerFD >= 0) {
|
||||
close(g_runTimerFD);
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "run timer close {ID}=%s", "{%d}",
|
||||
g_runTimerFD);
|
||||
g_runTimerFD = -1;
|
||||
}
|
||||
if (g_watchTimerFD >= 0) {
|
||||
close(g_watchTimerFD);
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_INFO, PID_LITEBUS_LOG, "watch timer close {ID}=%s", "{%d}",
|
||||
g_watchTimerFD);
|
||||
g_watchTimerFD = -1;
|
||||
}
|
||||
g_timersLock.Unlock();
|
||||
}
|
||||
|
||||
Timer TimerTools::AddTimer(const Duration &duration, const AID &aid, const std::function<void()> &thunk) {
|
||||
if (g_initStatus.load() == false) {
|
||||
return Timer();
|
||||
}
|
||||
if (duration == 0) {
|
||||
thunk();
|
||||
return Timer();
|
||||
}
|
||||
static std::atomic<uint64_t> id(1);
|
||||
TimeWatch timeWatch = TimeWatch::In(duration);
|
||||
Timer timer(id.fetch_add(1), timeWatch, aid, thunk);
|
||||
|
||||
// Add the timer to timerpoll and Schedule it
|
||||
g_timersLock.Lock();
|
||||
|
||||
if (g_timerPool->size() == 0 || timer.GetTimeWatch().Time() < g_timerPool->begin()->first) {
|
||||
(*g_timerPool)[timer.GetTimeWatch().Time()].push_back(timer);
|
||||
timer::ScheduleTick(*g_timerPool);
|
||||
} else {
|
||||
if (!(g_timerPool->size() >= 1)) {
|
||||
ICTSBASE_LOG_STRING(ICTSBASE_LOG_COMMON_CODE, HLOG_LEVEL_ERROR, PID_LITEBUS_LOG,
|
||||
"g_timerPool size invalid {size}=%s", "{%zd}", g_timerPool->size());
|
||||
}
|
||||
(*g_timerPool)[timer.GetTimeWatch().Time()].push_back(timer);
|
||||
}
|
||||
g_timersLock.Unlock();
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
bool TimerTools::Cancel(const Timer &timer) {
|
||||
if (g_initStatus.load() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool canceled = false;
|
||||
g_timersLock.Lock();
|
||||
Duration duration = timer.GetTimeWatch().Time();
|
||||
if (g_timerPool->count(duration) > 0) {
|
||||
canceled = true;
|
||||
(*g_timerPool)[duration].remove(timer);
|
||||
if ((*g_timerPool)[duration].empty()) {
|
||||
(void)(g_timerPool->erase(duration));
|
||||
}
|
||||
}
|
||||
g_timersLock.Unlock();
|
||||
|
||||
return canceled;
|
||||
}
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "timer/timewatch.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
||||
TimeWatch::TimeWatch() : duration(Now()) {}
|
||||
|
||||
TimeWatch::TimeWatch(const Duration &d) : duration(d) {}
|
||||
|
||||
TimeWatch::TimeWatch(const TimeWatch &that) : duration(that.duration) {}
|
||||
|
||||
TimeWatch::~TimeWatch() {}
|
||||
|
||||
Duration TimeWatch::Now() {
|
||||
struct timespec ts = {0, 0};
|
||||
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
Duration duration = ts.tv_sec * SECTOMILLI + (ts.tv_nsec / MICRTONANO) / MILLITOMICR;
|
||||
return duration;
|
||||
}
|
||||
|
||||
TimeWatch TimeWatch::In(const Duration &duration) { return TimeWatch(Now() + duration); }
|
||||
|
||||
TimeWatch &TimeWatch::operator=(const TimeWatch &that) {
|
||||
if (&that != this) {
|
||||
duration = that.duration;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TimeWatch &TimeWatch::operator=(const Duration &d) {
|
||||
duration = Now() + d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TimeWatch::operator==(const TimeWatch &that) const { return duration == that.duration; }
|
||||
|
||||
bool TimeWatch::operator<(const TimeWatch &that) const { return duration < that.duration; }
|
||||
|
||||
bool TimeWatch::operator<=(const TimeWatch &that) const { return duration <= that.duration; }
|
||||
|
||||
Duration TimeWatch::Time() const { return duration; }
|
||||
|
||||
Duration TimeWatch::Remaining() const {
|
||||
Duration nowTime = Now();
|
||||
return duration > nowTime ? (duration - nowTime) : 0;
|
||||
}
|
||||
|
||||
bool TimeWatch::Expired() const { return duration <= Now(); }
|
||||
|
||||
} // namespace mindspore
|
Loading…
Reference in New Issue