From 6d84df08802c40dffd6aef2f0dce1b2807fd8ed2 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 18 Jul 2016 11:54:00 +0200 Subject: [PATCH] Set thread state. --- src/mrimap.cpp | 49 +++++++++++++++++++++++++++++++---------------- src/mrimap.h | 19 +++++++++++++----- src/mrmailbox.cpp | 4 ++-- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/mrimap.cpp b/src/mrimap.cpp index 7057809b..964a1da4 100644 --- a/src/mrimap.cpp +++ b/src/mrimap.cpp @@ -26,7 +26,7 @@ ******************************************************************************* * * TODO: On Android, I think, the thread must be marked using - * AttachCurrentThread(), see MailCore2 code + * AttachCurrentThread(), see MailCore2 code and https://developer.android.com/training/articles/perf-jni.html * ******************************************************************************/ @@ -242,6 +242,8 @@ static void fetch_messages(MrImapThreadVal& threadval) void MrImap::WorkingThread() { // connect to server + m_threadState = MR_THREAD_CONNECT; + MrImapThreadVal threadval; int r; @@ -261,18 +263,24 @@ void MrImap::WorkingThread() { // wait for condition pthread_mutex_lock(&m_condmutex); + m_threadState = MR_THREAD_WAIT; pthread_cond_wait(&m_cond, &m_condmutex); // wait unlocks the mutex and waits for signal, if it returns, the mutex is locked again - int dowhat = m_dowhat; + MrImapThreadCmd cmd = m_threadCmd; + m_threadState = cmd; // make sure state or cmd blocks eg. Fetch() + m_threadCmd = MR_THREAD_WAIT; pthread_mutex_unlock(&m_condmutex); - switch( dowhat ) + switch( cmd ) { - case DO_FETCH: + case MR_THREAD_FETCH: fetch_messages(threadval); break; - case DO_EXIT: + case MR_THREAD_EXIT: goto WorkingThread_Exit; + + default: + break; // bad command } } @@ -283,7 +291,7 @@ WorkingThread_Exit: mailimap_free(threadval.m_imap); threadval.m_imap = NULL; } - m_threadRunning = false; + m_threadState = MR_THREAD_NOTALLOCATED; } @@ -295,7 +303,8 @@ WorkingThread_Exit: MrImap::MrImap(MrMailbox* mailbox) { m_mailbox = mailbox; - m_threadRunning = false; + m_threadState = MR_THREAD_NOTALLOCATED; + m_threadCmd = MR_THREAD_WAIT; m_loginParam = NULL; pthread_mutex_init(&m_condmutex, NULL); @@ -318,12 +327,12 @@ bool MrImap::Connect(const MrLoginParam* param) return false; // error, bad parameters } - if( m_threadRunning ) { + if( m_threadState!=MR_THREAD_NOTALLOCATED ) { return true; // already trying to connect } m_loginParam = param; - m_threadRunning = true; + m_threadState = MR_THREAD_INIT; pthread_create(&m_thread, NULL, (void * (*)(void *)) MrImap::StartupHelper, this); // success, so far, the real connection takes place in the working thread @@ -333,26 +342,32 @@ bool MrImap::Connect(const MrLoginParam* param) void MrImap::Disconnect() { - if( !m_threadRunning ) { + if( m_threadState==MR_THREAD_NOTALLOCATED ) { return; // already disconnected } - pthread_mutex_lock(&m_condmutex); - m_dowhat = DO_EXIT; - pthread_mutex_unlock(&m_condmutex); + if( m_threadState==MR_THREAD_EXIT || m_threadCmd==MR_THREAD_EXIT ) { + return; // already exiting/about to exit + } + + // raise exit signal + m_threadCmd = MR_THREAD_EXIT; pthread_cond_signal(&m_cond); } bool MrImap::Fetch() { - if( !m_threadRunning ) { + if( m_threadState==MR_THREAD_NOTALLOCATED ) { return false; // not connected } - pthread_mutex_lock(&m_condmutex); // if needed, we can use pthread_mutex_trylock() to avoid signalling if the thread is busy - m_dowhat = DO_FETCH; - pthread_mutex_unlock(&m_condmutex); + if( m_threadState==MR_THREAD_FETCH || m_threadCmd==MR_THREAD_FETCH ) { + return true; // already fetching/about to fetch + } + + // raise fetch signal + m_threadCmd = MR_THREAD_FETCH; pthread_cond_signal(&m_cond); // signal successfully raised; when and if fetching is started cannot be determinated by the return value diff --git a/src/mrimap.h b/src/mrimap.h index 6dfc6d2b..d39f2517 100644 --- a/src/mrimap.h +++ b/src/mrimap.h @@ -34,13 +34,24 @@ class MrMailbox; +enum MrImapThreadCmd +{ + MR_THREAD_NOTALLOCATED = 0 + ,MR_THREAD_INIT + ,MR_THREAD_CONNECT + ,MR_THREAD_WAIT + ,MR_THREAD_FETCH + ,MR_THREAD_EXIT +}; + + class MrImap { public: MrImap (MrMailbox* mailbox); ~MrImap (); - bool IsConnected () { return m_threadRunning; } + bool IsConnected () { return (m_threadState!=MR_THREAD_NOTALLOCATED); } bool Connect (const MrLoginParam*); void Disconnect (); bool Fetch (); @@ -50,13 +61,11 @@ private: const MrLoginParam* m_loginParam; pthread_t m_thread; - bool m_threadRunning; pthread_cond_t m_cond; pthread_mutex_t m_condmutex; - #define DO_FETCH 1 - #define DO_EXIT 2 - int m_dowhat; + MrImapThreadCmd m_threadState; // set by the working thread, the main thread can read this + MrImapThreadCmd m_threadCmd; // set by the main thread, read and reset by the working thread static void StartupHelper (MrImap* imap) { imap->WorkingThread(); } void WorkingThread (); diff --git a/src/mrmailbox.cpp b/src/mrmailbox.cpp index 383aed83..ec1821f5 100644 --- a/src/mrmailbox.cpp +++ b/src/mrmailbox.cpp @@ -195,8 +195,8 @@ char* MrMailbox::GetInfo() "SQLite version %s, threadsafe=%i\n" "libEtPan version %i.%i\n" "Database file %s\n" - "Chats/Messages %i/%i\n" "Contacts %i\n" + "Chats/Messages %i/%i\n" "mail_server %s\n" "mail_port %s\n" @@ -214,8 +214,8 @@ char* MrMailbox::GetInfo() , libetpan_get_version_major(), libetpan_get_version_minor() , dbfile? dbfile : unset - , chats, messages , contacts + , chats, messages , mail_server? mail_server : unset , mail_port? mail_port : unset