diff options
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r-- | sql/sql_class.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index e13b896c820..ae451bf9c83 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2250,6 +2250,109 @@ struct THD_count ~THD_count() { thread_count--; } }; +struct thd_async_state +{ + enum class enum_async_state + { + NONE, + SUSPEND, + RESUME + }; + enum_async_state m_state{ enum_async_state::NONE}; + enum enum_server_command m_command {COM_SLEEP}; + LEX_STRING m_packet{}; + + mysql_mutex_t m_mtx; + mysql_cond_t m_cond; + int m_pending_ops=0; + + thd_async_state() + { + mysql_mutex_init(0, &m_mtx, 0); + mysql_cond_init(0, &m_cond, 0); + } + /* + Only used with threadpool, where one can "suspend" and "resume" a THD. + Suspend only means leaving do_command earlier, while saving some state + Resume is continuing suspended do_command(), where it finished last time. + */ + bool try_suspend() + { + bool ret= true; + mysql_mutex_lock(&m_mtx); + DBUG_ASSERT(m_state == enum_async_state::NONE); + DBUG_ASSERT(m_pending_ops >= 0); + if (m_pending_ops == 0) + { + /* No pending operations, can't suspend, since nobody can resume */ + ret = false; + } + m_state= enum_async_state::SUSPEND; + mysql_mutex_unlock(&m_mtx); + return ret; + } + + ~thd_async_state() + { + wait_for_pending_ops(); + mysql_mutex_destroy(&m_mtx); + mysql_cond_destroy(&m_cond); + } + + /* + Increment pending asynchronous operations. + The client response may not be written if + this count > 0. + So, without threadpool query needs to wait for + the operations to finish. + With threadpool, THD can be suspended and resumed + when this counter goes to 0. + */ + void inc_pending_ops() + { + mysql_mutex_lock(&m_mtx); + m_pending_ops++; + mysql_mutex_unlock(&m_mtx); + } + + int dec_pending_ops() + { + mysql_mutex_lock(&m_mtx); + m_pending_ops--; + if (!m_pending_ops) + mysql_cond_signal(&m_cond); + mysql_mutex_unlock(&m_mtx); + return m_pending_ops; + } + + int pending_ops() + { + return m_pending_ops; + } + + /* Wait for pending operations to finish.*/ + void wait_for_pending_ops() + { + /* + It is fine to dirty read m_pending_ops and compare it with 0. + It is only incremented by the current thread, and may be decremented + by another one, so dirty read can be off and show positive number + when it is really 0 + */ + if (!m_pending_ops) + return; + mysql_mutex_lock(&m_mtx); + DBUG_ASSERT(m_pending_ops >= 0); + while (m_pending_ops) + mysql_cond_wait(&m_cond, &m_mtx); + mysql_mutex_unlock(&m_mtx); + } +}; + +extern "C" MYSQL_THD thd_increment_pending_ops(void); +extern "C" void thd_decrement_pending_ops(MYSQL_THD); +extern "C" int thd_pending_ops(MYSQL_THD); + /** @class THD @@ -4935,6 +5038,7 @@ private: } public: + thd_async_state async_state; #ifdef HAVE_REPLICATION /* If we do a purge of binary logs, log index info of the threads |