#ifndef PROTON_SESSION_SESSION_H_ #define PROTON_SESSION_SESSION_H_ #include "Context/Context.h" #include "Data/Metric.h" #include "Utility/Singleton.h" #include #include #include #include #include #include #include namespace proton { class Profiler; class Data; enum class OutputFormat; /// A session is a collection of profiler, context source, and data objects. /// There could be multiple sessions in the system, each can correspond to a /// different duration, or the same duration but with different configurations. class Session { public: ~Session() = default; void activate(); void deactivate(); void finalize(OutputFormat outputFormat); size_t getContextDepth(); private: Session(size_t id, const std::string &path, Profiler *profiler, std::unique_ptr contextSource, std::unique_ptr data) : id(id), path(path), profiler(profiler), contextSource(std::move(contextSource)), data(std::move(data)) {} template std::vector getInterfaces() { std::vector interfaces; // There's an implicit order between contextSource and profiler/data. The // latter two rely on the contextSource to obtain the context, so we need to // add the contextSource first. if (auto interface = dynamic_cast(contextSource.get())) { interfaces.push_back(interface); } if (auto interface = dynamic_cast(profiler)) { interfaces.push_back(interface); } if (auto interface = dynamic_cast(data.get())) { interfaces.push_back(interface); } return interfaces; } const std::string path{}; size_t id{}; Profiler *profiler{}; std::unique_ptr contextSource{}; std::unique_ptr data{}; friend class SessionManager; }; /// A session manager is responsible for managing the lifecycle of sessions. /// There's a single and unique session manager in the system. class SessionManager : public Singleton { public: SessionManager() = default; ~SessionManager() = default; size_t addSession(const std::string &path, const std::string &profilerName, const std::string &profilerPath, const std::string &contextSourceName, const std::string &dataName); void finalizeSession(size_t sessionId, OutputFormat outputFormat); void finalizeAllSessions(OutputFormat outputFormat); void activateSession(size_t sessionId); void activateAllSessions(); void deactivateSession(size_t sessionId); void deactivateAllSessions(); size_t getContextDepth(size_t sessionId); void enterScope(const Scope &scope); void exitScope(const Scope &scope); void enterOp(const Scope &scope); void exitOp(const Scope &scope); void addMetrics(size_t scopeId, const std::map &metrics); void setState(std::optional context); private: std::unique_ptr makeSession(size_t id, const std::string &path, const std::string &profilerName, const std::string &profilerPath, const std::string &contextSourceName, const std::string &dataName); void activateSessionImpl(size_t sessionId); void deActivateSessionImpl(size_t sessionId); size_t getSessionId(const std::string &path) { return sessionPaths[path]; } bool hasSession(const std::string &path) { return sessionPaths.find(path) != sessionPaths.end(); } bool hasSession(size_t sessionId) { return sessions.find(sessionId) != sessions.end(); } void removeSession(size_t sessionId); template void updateInterfaceCount(size_t sessionId, Counter &interfaceCounts) { auto interfaces = sessions[sessionId]->getInterfaces(); for (auto *interface : interfaces) { auto it = std::find_if( interfaceCounts.begin(), interfaceCounts.end(), [interface](const auto &pair) { return pair.first == interface; }); if (it != interfaceCounts.end()) { if constexpr (isRegistering) { ++it->second; } else { --it->second; if (it->second == 0) { interfaceCounts.erase(it); } } } else if constexpr (isRegistering) { interfaceCounts.emplace_back(interface, 1); } } } template void registerInterface(size_t sessionId, Counter &interfaceCounts) { updateInterfaceCount(sessionId, interfaceCounts); } template void unregisterInterface(size_t sessionId, Counter &interfaceCounts) { updateInterfaceCount(sessionId, interfaceCounts); } mutable std::mutex mutex; size_t nextSessionId{}; // path -> session id std::map sessionPaths; // session id -> active std::map sessionActive; // session id -> session std::map> sessions; // {scope, active count} std::vector> scopeInterfaceCounts; // {op, active count} std::vector> opInterfaceCounts; // {context source, active count} std::vector> contextSourceCounts; }; } // namespace proton #endif // PROTON_SESSION_H_