diff --git a/src/clientget.cpp b/src/clientget.cpp index 0a56934..f032881 100644 --- a/src/clientget.cpp +++ b/src/clientget.cpp @@ -7,6 +7,7 @@ #include #include +#include "utilpvt.h" #include "clientimpl.h" namespace pvxs { @@ -124,6 +125,8 @@ struct GPROp : public OperationBase Done, } state = Connecting; + INST_COUNTER(GPROp); + GPROp(operation_t op, const std::shared_ptr& chan) :OperationBase (op, chan) {} diff --git a/src/clientimpl.h b/src/clientimpl.h index e991e20..d0a3237 100644 --- a/src/clientimpl.h +++ b/src/clientimpl.h @@ -86,6 +86,8 @@ struct Connection : public ConnBase, public std::enable_shared_from_this& context, const SockAddr &peerAddr); virtual ~Connection(); @@ -148,6 +150,8 @@ struct Channel { // points to storage of Connection::opByIOID std::map opByIOID; + INST_COUNTER(Channel); + Channel(const std::shared_ptr& context, const std::string& name, uint32_t cid); ~Channel(); @@ -205,6 +209,8 @@ struct Context::Pvt const evevent beaconCleaner; + INST_COUNTER(ClientPvt); + Pvt(const Config& conf); ~Pvt(); diff --git a/src/clientintrospect.cpp b/src/clientintrospect.cpp index 1999a45..8927833 100644 --- a/src/clientintrospect.cpp +++ b/src/clientintrospect.cpp @@ -28,6 +28,8 @@ struct InfoOp : public OperationBase Done, } state = Connecting; + INST_COUNTER(InfoOp); + explicit InfoOp(const std::shared_ptr& chan) :OperationBase(Info, chan) {} diff --git a/src/clientmon.cpp b/src/clientmon.cpp index 3a542ad..0c6b36a 100644 --- a/src/clientmon.cpp +++ b/src/clientmon.cpp @@ -64,6 +64,8 @@ struct SubscriptionImpl : public OperationBase, public Subscription std::deque queue; uint32_t window =0u, unack =0u; + INST_COUNTER(SubscriptionImpl); + SubscriptionImpl(operation_t op, const std::shared_ptr& chan) :OperationBase (op, chan) ,channelName(chan->name) diff --git a/src/dataimpl.h b/src/dataimpl.h index 46164d1..b18fde6 100644 --- a/src/dataimpl.h +++ b/src/dataimpl.h @@ -140,6 +140,8 @@ struct StructTop { // empty, or the field of a structure which encloses this. std::weak_ptr enclosing; + + INST_COUNTER(StructTop); }; using Type = std::shared_ptr; diff --git a/src/pvxs/util.h b/src/pvxs/util.h index 4c58019..b53a1d1 100644 --- a/src/pvxs/util.h +++ b/src/pvxs/util.h @@ -7,6 +7,7 @@ #ifndef PVXS_UTIL_H #define PVXS_UTIL_H +#include #include #include #include @@ -104,6 +105,10 @@ public: #endif // !defined(__rtems__) && !defined(vxWorks) +//! return a snapshot of internal instance counters +PVXS_API +std::map instanceSnapshot(); + } // namespace pvxs #endif // PVXS_UTIL_H diff --git a/src/serverconn.h b/src/serverconn.h index 52fa972..cc3a446 100644 --- a/src/serverconn.h +++ b/src/serverconn.h @@ -69,6 +69,8 @@ struct ServerChannelControl : public server::ChannelControl const std::weak_ptr server; const std::weak_ptr chan; + + INST_COUNTER(ServerChannelControl); }; struct ServerChan @@ -91,6 +93,8 @@ struct ServerChan std::map > opByIOID; // our subset of ServerConn::opByIOID + INST_COUNTER(ServerChan); + ServerChan(const std::shared_ptr& conn, uint32_t sid, uint32_t cid, const std::string& name); ServerChan(const ServerChan&) = delete; ServerChan& operator=(const ServerChan&) = delete; @@ -110,6 +114,8 @@ struct ServerConn : public ConnBase, public std::enable_shared_from_this> backlog; + INST_COUNTER(ServerConn); + ServerConn(ServIface* iface, evutil_socket_t sock, struct sockaddr *peer, int socklen); ServerConn(const ServerConn&) = delete; ServerConn& operator=(const ServerConn&) = delete; @@ -174,6 +180,8 @@ struct ServerSource : public server::Source const Value info; + INST_COUNTER(ServerSource); + ServerSource(server::Server::Pvt* serv); virtual void onSearch(Search &op) override final; @@ -229,6 +237,8 @@ struct Server::Pvt Stopping, } state; + INST_COUNTER(ServerPvt); + Pvt(const Config& conf); ~Pvt(); diff --git a/src/serverget.cpp b/src/serverget.cpp index 06e149d..61dd429 100644 --- a/src/serverget.cpp +++ b/src/serverget.cpp @@ -136,6 +136,8 @@ struct ServerGPR : public ServerOp std::function&&, Value&&)> onPut; std::function&&)> onGet; + + INST_COUNTER(ServerGPR); }; @@ -246,6 +248,8 @@ struct ServerGPRConnect : public server::ConnectOp const std::weak_ptr server; const std::weak_ptr op; + + INST_COUNTER(ServerGPRConnect); }; struct ServerGPRExec : public server::ExecOp @@ -323,6 +327,8 @@ struct ServerGPRExec : public server::ExecOp const std::weak_ptr server; const std::weak_ptr op; + + INST_COUNTER(ServerGPRExec); }; } // namespace diff --git a/src/serverintrospect.cpp b/src/serverintrospect.cpp index 6b79e49..c4af738 100644 --- a/src/serverintrospect.cpp +++ b/src/serverintrospect.cpp @@ -48,6 +48,8 @@ struct ServerIntrospect : public ServerOp conn->opByIOID.erase(ioid); ch->opByIOID.erase(ioid); } + + INST_COUNTER(ServerIntrospect); }; struct ServerIntrospectControl : public server::ConnectOp @@ -125,6 +127,8 @@ struct ServerIntrospectControl : public server::ConnectOp const std::weak_ptr server; const std::weak_ptr op; + + INST_COUNTER(ServerIntrospectControl); }; } // namespace diff --git a/src/servermon.cpp b/src/servermon.cpp index 8d3466c..2f52e7b 100644 --- a/src/servermon.cpp +++ b/src/servermon.cpp @@ -55,6 +55,8 @@ struct MonitorOp : public ServerOp, std::deque queue; + INST_COUNTER(MonitorOp); + // caller must hold lock. // only used after State==Idle static @@ -319,6 +321,8 @@ struct ServerMonitorControl : public server::MonitorControlOp const std::weak_ptr server; const std::weak_ptr op; + + INST_COUNTER(ServerMonitorControl); }; struct ServerMonitorSetup : public server::MonitorSetupOp @@ -411,6 +415,8 @@ struct ServerMonitorSetup : public server::MonitorSetupOp const std::weak_ptr server; const std::weak_ptr op; + + INST_COUNTER(ServerMonitorSetup); }; diff --git a/src/sharedpv.cpp b/src/sharedpv.cpp index 574d9b7..3503f1c 100644 --- a/src/sharedpv.cpp +++ b/src/sharedpv.cpp @@ -45,6 +45,8 @@ struct SharedPV::Impl : public std::enable_shared_from_this std::set> subscribers; Value current; + + INST_COUNTER(SharedPVImpl); }; SharedPV SharedPV::buildMailbox() diff --git a/src/udp_collector.h b/src/udp_collector.h index be1608a..2fcb744 100644 --- a/src/udp_collector.h +++ b/src/udp_collector.h @@ -86,6 +86,9 @@ class PVXS_API UDPListener std::shared_ptr collector; const SockAddr dest; bool active; + + INST_COUNTER(UDPListener); + friend struct UDPCollector; friend struct UDPManager; diff --git a/src/util.cpp b/src/util.cpp index e5ca022..9010164 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -58,6 +58,76 @@ void cleanup_for_valgrind() impl::UDPManager::cleanup(); } + +#define CASE(KLASS) std::atomic cnt_ ## KLASS{} + +CASE(StructTop); + +CASE(UDPListener); + +CASE(GPROp); +CASE(Connection); +CASE(Channel); +CASE(ClientPvt); +CASE(InfoOp); +CASE(SubScriptionImpl); + +CASE(ServerChannelControl); +CASE(ServerChan); +CASE(ServerConn); +CASE(ServerSource); +CASE(ServerPvt); +CASE(ServerIntrospect); +CASE(ServerIntrospectControl); +CASE(ServerGPR); +CASE(ServerGPRConnect); +CASE(ServerGPRExec); +CASE(MonitorOp); +CASE(ServerMonitorControl); +CASE(ServerMonitorSetup); +CASE(SharedPVImpl); +CASE(SubscriptionImpl); + +#undef CASE + +std::map instanceSnapshot() +{ + std::map ret; + +#define CASE(KLASS) ret[#KLASS] = cnt_ ## KLASS .load(std::memory_order_relaxed) + +CASE(StructTop); + +CASE(UDPListener); + +CASE(GPROp); +CASE(Connection); +CASE(Channel); +CASE(ClientPvt); +CASE(InfoOp); +CASE(SubScriptionImpl); + +CASE(ServerChannelControl); +CASE(ServerChan); +CASE(ServerConn); +CASE(ServerSource); +CASE(ServerPvt); +CASE(ServerIntrospect); +CASE(ServerIntrospectControl); +CASE(ServerGPR); +CASE(ServerGPRConnect); +CASE(ServerGPRExec); +CASE(MonitorOp); +CASE(ServerMonitorControl); +CASE(ServerMonitorSetup); +CASE(SharedPVImpl); +CASE(SubscriptionImpl); + +#undef CASE + + return ret; +} + std::ostream& operator<<(std::ostream& strm, ArrayType code) { switch(code) { diff --git a/src/utilpvt.h b/src/utilpvt.h index 6f15327..795066b 100644 --- a/src/utilpvt.h +++ b/src/utilpvt.h @@ -13,6 +13,7 @@ # include #endif +#include #include #include #include @@ -233,6 +234,46 @@ public: PVXS_API std::ostream& operator<<(std::ostream& strm, const SockAddr& addr); +template* Cnt> +struct InstCounter +{ + InstCounter() {(*Cnt).fetch_add(1, std::memory_order_relaxed);} + ~InstCounter() {(*Cnt).fetch_sub(1, std::memory_order_relaxed);} +}; + +#define INST_COUNTER(KLASS) InstCounter<&cnt_ ## KLASS> instances + +#define CASE(KLASS) extern std::atomic cnt_ ## KLASS + +CASE(StructTop); + +CASE(UDPListener); + +CASE(GPROp); +CASE(Connection); +CASE(Channel); +CASE(ClientPvt); +CASE(InfoOp); +CASE(SubScriptionImpl); + +CASE(ServerChannelControl); +CASE(ServerChan); +CASE(ServerConn); +CASE(ServerSource); +CASE(ServerPvt); +CASE(ServerIntrospect); +CASE(ServerIntrospectControl); +CASE(ServerGPR); +CASE(ServerGPRConnect); +CASE(ServerGPRExec); +CASE(MonitorOp); +CASE(ServerMonitorControl); +CASE(ServerMonitorSetup); +CASE(SharedPVImpl); +CASE(SubscriptionImpl); + +#undef CASE + } // namespace pvxs #endif // UTILPVT_H