summaryrefslogtreecommitdiff
path: root/sql/sql_class.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r--sql/sql_class.h104
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