#ifndef ASYNCDBCONNECTION_H #define ASYNCDBCONNECTION_H #include "PgsqlConn.h" #include "Pgsql_Params.h" #include "win32event.h" #include "connectionconfig.h" #include #include #include #include #include #include /** \brief Class that handles asynchronous execution of queries. * * Queries are passed to this class with a routine to call on completion * when the result is on that routine is called. */ class ASyncDBConnection { public: enum class State { NotConnected, Connecting, Connected, QuerySend, CancelSend, Terminating }; using on_result_callback = std::function, qint64)>; using on_state_callback = std::function; using on_notice_callback = std::function; ASyncDBConnection(); State state() const; // void setupConnection(const std::string &connstring); void setupConnection(const ConnectionConfig &config); void closeConnection(); void setStateCallback(on_state_callback state_callback); void setNoticeCallback(on_notice_callback notice_callback); /** Sends command to the server. When the result is in on_result will be called directly within the thread. If the command gives multiple results on_result will be called for each result. */ bool send(const std::string &command, on_result_callback on_result); bool send(const std::string &command, Pgsql::Params params, on_result_callback on_result); bool cancel(); private: class Command { public: std::string command; Pgsql::Params params; on_result_callback on_result; Command() = default; Command(const std::string &cmd, on_result_callback cb) : command(cmd), on_result(cb) {} Command(const std::string &cmd, Pgsql::Params &&p, on_result_callback cb) : command(cmd), params(p), on_result(cb) {} }; /// Contains all the members accessed by the thread class Thread { public: using t_CommandQueue = std::queue; struct { std::mutex m_mutex; on_state_callback m_func; } m_stateCallback; struct { std::mutex m_mutex; on_notice_callback m_func; } m_noticeCallback; struct t_Command { std::mutex m_mutex; t_CommandQueue m_queue; Win32Event m_newEvent; t_Command() : m_newEvent(Win32Event::Reset::Auto, Win32Event::Initial::Clear) {} } m_commandQueue; // std::string m_initString; ConnectionConfig m_config; State m_state = State::NotConnected; Thread(); /// Is started as a seperate thread by ASyncDBConnection void run(); /// Sends a cancel request to the DB server bool cancel(); void stop(); private: Win32Event m_stopEvent; Pgsql::Connection m_connection; bool terminateRequested = false; ///< is set when the thread should stop bool m_terminated = true; Pgsql::Canceller m_canceller; QElapsedTimer m_timer; bool makeConnection(); void communicate(); void doStateCallback(State state); /// Wait's for a command to come in and send's it to the server void waitForAndSendCommand(); void doNewCommand(); void waitForResult(); void processNotice(const PGresult *result); }; Thread m_threadData; std::thread m_thread; }; #endif // ASYNCDBCONNECTION_H