diff options
author | Determinant <[email protected]> | 2018-07-20 20:08:59 -0400 |
---|---|---|
committer | Determinant <[email protected]> | 2018-07-20 20:08:59 -0400 |
commit | 0465243c710ede74a78885077140d8673efbc647 (patch) | |
tree | d8b36060c31b6168d0967fd7f6e70d841aceed0f /include | |
parent | 0bd0ddd69c5f6d5f59fcf73a943491ba026b2c4c (diff) |
improve msg & msg network interface
Diffstat (limited to 'include')
-rw-r--r-- | include/salticidae/msg.h | 56 | ||||
-rw-r--r-- | include/salticidae/network.h | 263 | ||||
-rw-r--r-- | include/salticidae/ref.h | 19 |
3 files changed, 180 insertions, 158 deletions
diff --git a/include/salticidae/msg.h b/include/salticidae/msg.h index 33f0d2b..8a63a50 100644 --- a/include/salticidae/msg.h +++ b/include/salticidae/msg.h @@ -36,14 +36,10 @@ namespace salticidae { -template<typename OpcodeType = uint8_t, - const OpcodeType PING = 0xf0, - const OpcodeType PONG = 0xf1> +template<typename OpcodeType> class MsgBase { public: using opcode_t = OpcodeType; - static const opcode_t OPCODE_PING; - static const opcode_t OPCODE_PONG; static const size_t header_size; private: @@ -195,32 +191,6 @@ class MsgBase { return std::move(s); } - void gen_ping(uint16_t port) { - DataStream s; - set_opcode(OPCODE_PING); - s << htole(port); - set_payload(std::move(s)); - } - - void parse_ping(uint16_t &port) const { - DataStream s(get_payload()); - s >> port; - port = letoh(port); - } - - void gen_pong(uint16_t port) { - DataStream s; - set_opcode(OPCODE_PONG); - s << htole(port); - set_payload(std::move(s)); - } - - void parse_pong(uint16_t &port) const { - DataStream s(get_payload()); - s >> port; - port = letoh(port); - } - void gen_hash_list(DataStream &s, const std::vector<uint256_t> &hashes) { uint32_t size = htole((uint32_t)hashes.size()); @@ -242,24 +212,12 @@ class MsgBase { }; -template<typename OpcodeType, - OpcodeType _, - OpcodeType __> -const size_t MsgBase<OpcodeType, _, __>::header_size = - sizeof(MsgBase<OpcodeType, _, __>::magic) + - sizeof(MsgBase<OpcodeType, _, __>::opcode) + - sizeof(MsgBase<OpcodeType, _, __>::length) + - sizeof(MsgBase<OpcodeType, _, __>::checksum); - -template<typename OpcodeType, - OpcodeType PING, - OpcodeType _> -const OpcodeType MsgBase<OpcodeType, PING, _>::OPCODE_PING = PING; - -template<typename OpcodeType, - OpcodeType _, - OpcodeType PONG> -const OpcodeType MsgBase<OpcodeType, _, PONG>::OPCODE_PONG = PONG; +template<typename OpcodeType> +const size_t MsgBase<OpcodeType>::header_size = + sizeof(MsgBase<OpcodeType>::magic) + + sizeof(MsgBase<OpcodeType>::opcode) + + sizeof(MsgBase<OpcodeType>::length) + + sizeof(MsgBase<OpcodeType>::checksum); } diff --git a/include/salticidae/network.h b/include/salticidae/network.h index 0ea7455..1e0f560 100644 --- a/include/salticidae/network.h +++ b/include/salticidae/network.h @@ -32,16 +32,51 @@ namespace salticidae { +template<typename ClassType, typename ReturnType, typename... Args, typename... FArgs> +inline auto handler_bind(ReturnType(ClassType::* f)(Args...), FArgs&&... fargs) { + return std::function<ReturnType(Args...)>(std::bind(f, std::forward<FArgs>(fargs)...)); +} + /** Network of nodes who can send async messages. */ -template<typename MsgType> +template<typename OpcodeType> class MsgNetwork: public ConnPool { public: + using Msg = MsgBase<OpcodeType>; + /* match lambdas */ + template<typename T> + struct callback_traits: + public callback_traits<decltype(&T::operator())> {}; + + /* match plain functions */ + template<typename ReturnType, typename MsgType, typename ConnType> + struct callback_traits<ReturnType(MsgType, ConnType)> { + using ret_type = ReturnType; + using conn_type = ConnType; + using msg_type = typename std::remove_reference<MsgType>::type; + }; + + /* match function pointers */ + template<typename ReturnType, typename... Args> + struct callback_traits<ReturnType(*)(Args...)>: + public callback_traits<ReturnType(Args...)> {}; + + /* match const member functions */ + template<typename ClassType, typename ReturnType, typename... Args> + struct callback_traits<ReturnType(ClassType::*)(Args...) const>: + public callback_traits<ReturnType(Args...)> {}; + + /* match member functions */ + template<typename ClassType, typename ReturnType, typename... Args> + struct callback_traits<ReturnType(ClassType::*)(Args...)>: + public callback_traits<ReturnType(Args...)> {}; + class Conn: public ConnPool::Conn { enum MsgState { HEADER, PAYLOAD }; - MsgType msg; + + Msg msg; MsgState msg_state; MsgNetwork *mn; @@ -74,13 +109,13 @@ class MsgNetwork: public ConnPool { }; using conn_t = RcObj<Conn>; - using msg_callback_t = std::function<void(const MsgType &msg, conn_t conn)>; + using msg_callback_t = std::function<void(const Msg &msg, conn_t conn)>; #ifdef SALTICIDAE_MSG_STAT class msg_stat_by_opcode_t: - public std::unordered_map<typename MsgType::opcode_t, + public std::unordered_map<typename Msg::opcode_t, std::pair<uint32_t, size_t>> { public: - void add(const MsgType &msg) { + void add(const Msg &msg) { auto &p = this->operator[](msg.get_opcode()); p.first++; p.second += msg.get_length(); @@ -89,7 +124,7 @@ class MsgNetwork: public ConnPool { #endif private: - std::unordered_map<typename MsgType::opcode_t, + std::unordered_map<typename Msg::opcode_t, msg_callback_t> handler_map; protected: @@ -101,6 +136,7 @@ class MsgNetwork: public ConnPool { ConnPool::conn_t create_conn() override { return (new Conn(this))->self(); } public: + MsgNetwork(const EventContext &eb, int max_listen_backlog, double conn_server_timeout, @@ -109,7 +145,18 @@ class MsgNetwork: public ConnPool { conn_server_timeout, seg_buff_size) {} - void reg_handler(typename MsgType::opcode_t opcode, msg_callback_t handler); + template<typename Func> + typename std::enable_if<std::is_constructible< + typename callback_traits<Func>::msg_type, DataStream &&>::value>::type + reg_handler(Func handler) { + using callback_t = callback_traits<Func>; + handler_map[callback_t::msg_type::opcode] = [handler](const Msg &msg, conn_t conn) { + handler(typename callback_t::msg_type(msg.get_payload()), + static_pointer_cast<typename callback_t::conn_type::type>(conn)); + }; + } + + template<typename MsgType> void send_msg(const MsgType &msg, conn_t conn); using ConnPool::listen; #ifdef SALTICIDAE_MSG_STAT @@ -126,9 +173,10 @@ class MsgNetwork: public ConnPool { }; /** Simple network that handles client-server requests. */ -template<typename MsgType> -class ClientNetwork: public MsgNetwork<MsgType> { - using MsgNet = MsgNetwork<MsgType>; +template<typename OpcodeType> +class ClientNetwork: public MsgNetwork<OpcodeType> { + using MsgNet = MsgNetwork<OpcodeType>; + using Msg = typename MsgNet::Msg; std::unordered_map<NetAddr, typename MsgNet::conn_t> addr2conn; public: @@ -159,6 +207,7 @@ class ClientNetwork: public MsgNetwork<MsgType> { conn_server_timeout, seg_buff_size) {} + template<typename MsgType> void send_msg(const MsgType &msg, const NetAddr &addr); conn_t connect(const NetAddr &addr) = delete; }; @@ -169,9 +218,12 @@ class PeerNetworkError: public SalticidaeError { /** Peer-to-peer network where any two nodes could hold a bi-diretional message * channel, established by either side. */ -template<typename MsgType> -class PeerNetwork: public MsgNetwork<MsgType> { - using MsgNet= MsgNetwork<MsgType>; +template<typename OpcodeType = uint8_t, + OpcodeType OPCODE_PING = 0xf0, + OpcodeType OPCODE_PONG = 0xf1> +class PeerNetwork: public MsgNetwork<OpcodeType> { + using MsgNet = MsgNetwork<OpcodeType>; + using Msg = typename MsgNet::Msg; public: enum IdentityMode { IP_BASED, @@ -244,8 +296,34 @@ class PeerNetwork: public MsgNetwork<MsgType> { double conn_timeout; uint16_t listen_port; - void msg_ping(const MsgType &msg, ConnPool::conn_t conn); - void msg_pong(const MsgType &msg, ConnPool::conn_t conn); + struct MsgPing { + static const OpcodeType opcode; + DataStream serialized; + uint16_t port; + MsgPing(uint16_t port) { + serialized << htole(port); + } + MsgPing(DataStream &&s) { + s >> port; + port = letoh(port); + } + }; + + struct MsgPong { + static const OpcodeType opcode; + DataStream serialized; + uint16_t port; + MsgPong(uint16_t port) { + serialized << htole(port); + } + MsgPong(DataStream &&s) { + s >> port; + port = letoh(port); + } + }; + + void msg_ping(MsgPing &&msg, conn_t conn); + void msg_pong(MsgPong &&msg, conn_t conn); void reset_conn_timeout(conn_t conn); bool check_new_conn(conn_t conn, uint16_t port); void start_active_conn(const NetAddr &paddr); @@ -275,7 +353,9 @@ class PeerNetwork: public MsgNetwork<MsgType> { void add_peer(const NetAddr &paddr); const conn_t get_peer_conn(const NetAddr &paddr) const; + template<typename MsgType> void send_msg(const MsgType &msg, const Peer *peer); + template<typename MsgType> void send_msg(const MsgType &msg, const NetAddr &paddr); void listen(NetAddr listen_addr); bool has_peer(const NetAddr &paddr) const; @@ -285,18 +365,18 @@ class PeerNetwork: public MsgNetwork<MsgType> { } }; -template<typename MsgType> -void MsgNetwork<MsgType>::Conn::on_read() { +template<typename OpcodeType> +void MsgNetwork<OpcodeType>::Conn::on_read() { auto &recv_buffer = read(); auto conn = static_pointer_cast<Conn>(self()); while (get_fd() != -1) { if (msg_state == Conn::HEADER) { - if (recv_buffer.size() < MsgType::header_size) break; + if (recv_buffer.size() < Msg::header_size) break; /* new header available */ - bytearray_t data = recv_buffer.pop(MsgType::header_size); - msg = MsgType(data.data()); + bytearray_t data = recv_buffer.pop(Msg::header_size); + msg = Msg(data.data()); msg_state = Conn::PAYLOAD; } if (msg_state == Conn::PAYLOAD) @@ -331,8 +411,8 @@ void MsgNetwork<MsgType>::Conn::on_read() { } } -template<typename MsgType> -void PeerNetwork<MsgType>::Peer::reset_conn(conn_t new_conn) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Peer::reset_conn(conn_t new_conn) { if (conn != new_conn) { if (conn) @@ -348,23 +428,21 @@ void PeerNetwork<MsgType>::Peer::reset_conn(conn_t new_conn) { clear_all_events(); } -template<typename MsgType> -void PeerNetwork<MsgType>::Conn::on_setup() { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Conn::on_setup() { assert(!ev_timeout); ev_timeout = Event(pn->eb, -1, 0, [this](evutil_socket_t, short) { SALTICIDAE_LOG_INFO("peer ping-pong timeout"); this->terminate(); }); /* the initial ping-pong to set up the connection */ - MsgType ping; - ping.gen_ping(pn->listen_port); auto conn = static_pointer_cast<Conn>(this->self()); pn->reset_conn_timeout(conn); - pn->MsgNet::send_msg(ping, conn); + pn->MsgNet::send_msg(MsgPing(pn->listen_port), conn); } -template<typename MsgType> -void PeerNetwork<MsgType>::Conn::on_teardown() { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Conn::on_teardown() { auto it = pn->id2peer.find(peer_id); if (it == pn->id2peer.end()) return; auto p = it->second.get(); @@ -383,8 +461,8 @@ void PeerNetwork<MsgType>::Conn::on_teardown() { p->ev_retry_timer.add_with_timeout(pn->gen_conn_timeout()); } -template<typename MsgType> -bool PeerNetwork<MsgType>::check_new_conn(conn_t conn, uint16_t port) { +template<typename O, O _, O __> +bool PeerNetwork<O, _, __>::check_new_conn(conn_t conn, uint16_t port) { if (conn->peer_id.is_null()) { /* passive connections can eventually have ids after getting the port number in IP_BASED_PORT mode */ @@ -412,21 +490,18 @@ bool PeerNetwork<MsgType>::check_new_conn(conn_t conn, uint16_t port) { return false; } -template<typename MsgType> -void PeerNetwork<MsgType>::msg_ping(const MsgType &msg, ConnPool::conn_t conn_) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::msg_ping(MsgPing &&msg, conn_t conn_) { auto conn = static_pointer_cast<Conn>(conn_); - uint16_t port; - msg.parse_ping(port); + uint16_t port = msg.port; SALTICIDAE_LOG_INFO("ping from %s, port %u", std::string(*conn).c_str(), ntohs(port)); if (check_new_conn(conn, port)) return; auto p = id2peer.find(conn->peer_id)->second.get(); - MsgType pong; - pong.gen_pong(this->listen_port); - send_msg(pong, p); + send_msg(MsgPong(this->listen_port), p); } -template<typename MsgType> -void PeerNetwork<MsgType>::msg_pong(const MsgType &msg, ConnPool::conn_t conn_) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::msg_pong(MsgPong &&msg, conn_t conn_) { auto conn = static_pointer_cast<Conn>(conn_); auto it = id2peer.find(conn->peer_id); if (it == id2peer.end()) @@ -435,8 +510,7 @@ void PeerNetwork<MsgType>::msg_pong(const MsgType &msg, ConnPool::conn_t conn_) return; } auto p = it->second.get(); - uint16_t port; - msg.parse_pong(port); + uint16_t port = msg.port; if (check_new_conn(conn, port)) return; p->pong_msg_ok = true; if (p->ping_timer_ok) @@ -446,18 +520,16 @@ void PeerNetwork<MsgType>::msg_pong(const MsgType &msg, ConnPool::conn_t conn_) } } -template<typename MsgType> -void PeerNetwork<MsgType>::listen(NetAddr listen_addr) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::listen(NetAddr listen_addr) { MsgNet::listen(listen_addr); listen_port = listen_addr.port; - this->reg_handler(MsgType::OPCODE_PING, - std::bind(&PeerNetwork::msg_ping, this, _1, _2)); - this->reg_handler(MsgType::OPCODE_PONG, - std::bind(&PeerNetwork::msg_pong, this, _1, _2)); + this->reg_handler(handler_bind(&PeerNetwork::msg_ping, this, _1, _2)); + this->reg_handler(handler_bind(&PeerNetwork::msg_pong, this, _1, _2)); } -template<typename MsgType> -void PeerNetwork<MsgType>::start_active_conn(const NetAddr &addr) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::start_active_conn(const NetAddr &addr) { auto p = id2peer.find(addr)->second.get(); if (p->connected) return; auto conn = static_pointer_cast<Conn>(connect(addr)); @@ -468,8 +540,8 @@ void PeerNetwork<MsgType>::start_active_conn(const NetAddr &addr) { conn->peer_id.port = 0; } -template<typename MsgType> -void PeerNetwork<MsgType>::add_peer(const NetAddr &addr) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::add_peer(const NetAddr &addr) { auto it = id2peer.find(addr); if (it != id2peer.end()) throw PeerNetworkError("peer already exists"); @@ -478,28 +550,26 @@ void PeerNetwork<MsgType>::add_peer(const NetAddr &addr) { start_active_conn(addr); } -template<typename MsgType> -const typename PeerNetwork<MsgType>::conn_t -PeerNetwork<MsgType>::get_peer_conn(const NetAddr &paddr) const { +template<typename O, O _, O __> +const typename PeerNetwork<O, _, __>::conn_t +PeerNetwork<O, _, __>::get_peer_conn(const NetAddr &paddr) const { auto it = id2peer.find(paddr); if (it == id2peer.end()) throw PeerNetworkError("peer does not exist"); return it->second->conn; } -template<typename MsgType> -bool PeerNetwork<MsgType>::has_peer(const NetAddr &paddr) const { +template<typename O, O _, O __> +bool PeerNetwork<O, _, __>::has_peer(const NetAddr &paddr) const { return id2peer.count(paddr); } +template<typename OpcodeType> template<typename MsgType> -void MsgNetwork<MsgType>::reg_handler(typename MsgType::opcode_t opcode, - msg_callback_t handler) { - handler_map[opcode] = handler; -} - -template<typename MsgType> -void MsgNetwork<MsgType>::send_msg(const MsgType &msg, conn_t conn) { +void MsgNetwork<OpcodeType>::send_msg(const MsgType &_msg, conn_t conn) { + Msg msg; + msg.set_opcode(MsgType::opcode); + msg.set_payload(std::move(_msg.serialized)); bytearray_t msg_data = msg.serialize(); SALTICIDAE_LOG_DEBUG("wrote message %s to %s", std::string(msg).c_str(), @@ -511,65 +581,53 @@ void MsgNetwork<MsgType>::send_msg(const MsgType &msg, conn_t conn) { #endif } +template<typename O, O _, O __> template<typename MsgType> -void PeerNetwork<MsgType>::send_msg(const MsgType &msg, const Peer *peer) { - bytearray_t msg_data = msg.serialize(); - SALTICIDAE_LOG_DEBUG("wrote message %s to %s", - std::string(msg).c_str(), - std::string(peer->addr).c_str()); +void PeerNetwork<O, _, __>::send_msg(const MsgType &msg, const Peer *peer) { if (peer->connected) - { - SALTICIDAE_LOG_DEBUG("wrote to ConnPool"); - peer->conn->write(std::move(msg_data)); - } + MsgNet::send_msg(msg, peer->conn); else - { SALTICIDAE_LOG_DEBUG("dropped"); - } -#ifdef SALTICIDAE_MSG_STAT - peer->conn->nsent++; - this->sent_by_opcode.add(msg); -#endif } +template<typename O, O _, O __> template<typename MsgType> -void PeerNetwork<MsgType>::send_msg(const MsgType &msg, const NetAddr &addr) { +void PeerNetwork<O, _, __>::send_msg(const MsgType &msg, const NetAddr &addr) { auto it = id2peer.find(addr); if (it == id2peer.end()) { - SALTICIDAE_LOG_ERROR("sending to non-existing peer: %s", std::string(addr).c_str()); + SALTICIDAE_LOG_ERROR("sending to non-existing peer: %s", + std::string(addr).c_str()); throw PeerNetworkError("peer does not exist"); } send_msg(msg, it->second.get()); } -template<typename MsgType> -void PeerNetwork<MsgType>::Peer::reset_ping_timer() { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Peer::reset_ping_timer() { assert(ev_ping_timer); ev_ping_timer.del(); ev_ping_timer.add_with_timeout(gen_rand_timeout(pn->ping_period)); } -template<typename MsgType> -void PeerNetwork<MsgType>::reset_conn_timeout(conn_t conn) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::reset_conn_timeout(conn_t conn) { assert(conn->ev_timeout); conn->ev_timeout.del(); conn->ev_timeout.add_with_timeout(conn_timeout); SALTICIDAE_LOG_INFO("reset timeout %.2f", conn_timeout); } -template<typename MsgType> -void PeerNetwork<MsgType>::Peer::send_ping() { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Peer::send_ping() { ping_timer_ok = false; pong_msg_ok = false; - MsgType ping; - ping.gen_ping(pn->listen_port); pn->reset_conn_timeout(conn); - pn->send_msg(ping, this); + pn->send_msg(MsgPing(pn->listen_port), this); } -template<typename MsgType> -void PeerNetwork<MsgType>::Peer::ping_timer(evutil_socket_t, short) { +template<typename O, O _, O __> +void PeerNetwork<O, _, __>::Peer::ping_timer(evutil_socket_t, short) { ping_timer_ok = true; if (pong_msg_ok) { @@ -578,13 +636,13 @@ void PeerNetwork<MsgType>::Peer::ping_timer(evutil_socket_t, short) { } } -template<typename MsgType> -const std::vector<NetAddr> &PeerNetwork<MsgType>::all_peers() const { +template<typename O, O _, O __> +const std::vector<NetAddr> &PeerNetwork<O, _, __>::all_peers() const { return peer_list; } -template<typename MsgType> -void ClientNetwork<MsgType>::Conn::on_setup() { +template<typename OpcodeType> +void ClientNetwork<OpcodeType>::Conn::on_setup() { assert(this->get_mode() == Conn::PASSIVE); const auto &addr = this->get_addr(); cn->addr2conn.erase(addr); @@ -593,19 +651,26 @@ void ClientNetwork<MsgType>::Conn::on_setup() { static_pointer_cast<Conn>(this->self()))); } -template<typename MsgType> -void ClientNetwork<MsgType>::Conn::on_teardown() { +template<typename OpcodeType> +void ClientNetwork<OpcodeType>::Conn::on_teardown() { assert(this->get_mode() == Conn::PASSIVE); cn->addr2conn.erase(this->get_addr()); } +template<typename OpcodeType> template<typename MsgType> -void ClientNetwork<MsgType>::send_msg(const MsgType &msg, const NetAddr &addr) { +void ClientNetwork<OpcodeType>::send_msg(const MsgType &msg, const NetAddr &addr) { auto it = addr2conn.find(addr); if (it == addr2conn.end()) return; MsgNet::send_msg(msg, it->second); } +template<typename O, O OPCODE_PING, O _> +const O PeerNetwork<O, OPCODE_PING, _>::MsgPing::opcode = OPCODE_PING; + +template<typename O, O _, O OPCODE_PONG> +const O PeerNetwork<O, _, OPCODE_PONG>::MsgPong::opcode = OPCODE_PONG; + } #endif diff --git a/include/salticidae/ref.h b/include/salticidae/ref.h index 92d6b0d..f97bd43 100644 --- a/include/salticidae/ref.h +++ b/include/salticidae/ref.h @@ -59,8 +59,7 @@ template<typename T, typename D> class BoxObj; template<typename T, typename D> class _BoxObj { protected: - using ptr_type = T *; - ptr_type obj; + T *obj; template<typename T_, typename R, typename D_> friend class _RcObjBase; @@ -68,9 +67,9 @@ class _BoxObj { friend class _BoxObj; public: - + using type = T; constexpr _BoxObj(): obj(nullptr) {} - constexpr _BoxObj(ptr_type obj): obj(obj) {} + constexpr _BoxObj(T *obj): obj(obj) {} _BoxObj(const _BoxObj &other) = delete; _BoxObj(_BoxObj &&other): obj(other.obj) { other.obj = nullptr; @@ -144,7 +143,7 @@ class BoxObj<T[], D>: public _BoxObj<T, D> { template<typename T, typename D = default_delete<T>, typename T_, typename D_> BoxObj<T, D> static_pointer_cast(BoxObj<T_, D_> &&other) { BoxObj<T, D> box{}; - box.obj = static_cast<typename BoxObj<T, D>::ptr_type>(other.obj); + box.obj = static_cast<typename BoxObj<T, D>::type *>(other.obj); return std::move(box); } @@ -280,8 +279,7 @@ class WeakObjBase<T[], R>: public _WeakObjBase<T, R> { template<typename T, typename R, typename D> class _RcObjBase { protected: - using ptr_type = T *; - ptr_type obj; + T *obj; R *ctl; friend _WeakObjBase<T, R>; @@ -289,8 +287,9 @@ class _RcObjBase { friend class _RcObjBase; public: + using type = T; _RcObjBase(): obj(nullptr), ctl(nullptr) {} - _RcObjBase(ptr_type obj): obj(obj), ctl(new R()) {} + _RcObjBase(T *obj): obj(obj), ctl(new R()) {} _RcObjBase(BoxObj<T> &&box_ref): obj(box_ref.obj), ctl(new R()) { box_ref.obj = nullptr; } @@ -438,7 +437,7 @@ template<typename T, typename D = default_delete<T>, typename T_, typename R_, typename D_> RcObjBase<T, R_, D> static_pointer_cast(const RcObjBase<T_, R_, D_> &other) { RcObjBase<T, R_, D> rc{}; - rc.obj = static_cast<typename RcObjBase<T, R_, D>::ptr_type>(other.obj); + rc.obj = static_cast<typename RcObjBase<T, R_, D>::type *>(other.obj); if ((rc.ctl = other.ctl)) rc.ctl->add_ref(); return std::move(rc); @@ -448,7 +447,7 @@ template<typename T, typename D = default_delete<T>, typename T_, typename R_, typename D_> RcObjBase<T, R_, D> static_pointer_cast(RcObjBase<T_, R_, D_> &&other) { RcObjBase<T, R_, D> rc{}; - rc.obj = static_cast<typename RcObjBase<T, R_, D>::ptr_type>(other.obj); + rc.obj = static_cast<typename RcObjBase<T, R_, D>::type *>(other.obj); rc.ctl = other.ctl; other.ctl = nullptr; return std::move(rc); |