From 1830e05ad4eefee5f50fe1e6b83c26dc680852a7 Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Sun, 27 Jul 2008 01:06:01 +0000 Subject: [PATCH] MGR: async GUI RPCs: disallow events while processing demand RPCs, wait 1250ms before Please Wait dialog. svn path=/workspaces/charlief/; revision=15686 --- checkin_notes | 45 +++++++++++++++++++++++++++ clientgui/AsyncRPC.cpp | 62 +++++++++++++++++++++++++++++--------- clientgui/AsyncRPC.h | 3 +- clientgui/MainDocument.cpp | 7 +++-- clientgui/MainDocument.h | 2 +- 5 files changed, 99 insertions(+), 20 deletions(-) diff --git a/checkin_notes b/checkin_notes index 9524d195df..e4457505b9 100644 --- a/checkin_notes +++ b/checkin_notes @@ -5994,6 +5994,19 @@ Charlie 23 July 2008 BOINCGUIApp.cpp,.h MainDocument.cpp,.h +David 24 July 2008 + - web: fix profile rate + + html/user/ + profile_rate.php + +David 24 July 2008 + - client: report all errors in parsing app_info.xml files + Fixes #703 + + client/ + cs_statefile.C + Charlie 24 July 2008 - MGR: async GUI RPCs: Get RPCs all working in separate thread; temporarily ignore timer events which would do RPCs while @@ -6010,6 +6023,26 @@ Charlie 24 July 2008 sg_DlgMessages.cpp sg_ProjectsComponent.cpp +Rom 25 July 2008 + - Tag for 6.3.6 release, all platforms + boinc_core_release_6_3_6 + + / + configure.ac + version.h + +David 25 July 2008 + - back-end stuff to support Python MW (from Adam Kornafeld) + Not complete. + + py/Boinc/ + projectxml.py + sched/ + assimilate_handler.h + assimilator.C + tools/ + pymw_setup + Charlie 25 July 2008 - MGR: async GUI RPCs: Implement first Periodic RPCs called from a timer event for CachedStateUpdate(), ForceCacheUpdate(), @@ -6021,3 +6054,15 @@ Charlie 25 July 2008 BOINCBaseFrame.cpp,.h Events.h MainDocument.cpp,.h + +Charlie 26 July 2008 + - MGR: async GUI RPCs: Simulate handling of CRPCFinishedEvent but + don't allow any other events (so allow no user activity) while + processing demand RPCs. This avoids the ugly "flashing" of + windows caused by wxSafeYield() disabling the controls. + Increase delay before displaying Please Wait dialog from 250 + to 1250 milliseconds. + + clientgui/ + AsyncRPC.cpp,h + MainDocument.cpp,.h diff --git a/clientgui/AsyncRPC.cpp b/clientgui/AsyncRPC.cpp index 9f994edf9b..869699f301 100644 --- a/clientgui/AsyncRPC.cpp +++ b/clientgui/AsyncRPC.cpp @@ -31,7 +31,7 @@ #include "BOINCBaseFrame.h" // Delay in milliseconds before showing AsyncRPCDlg -#define RPC_WAIT_DLG_DELAY 250 +#define RPC_WAIT_DLG_DELAY 1500 bool LogRPCs = false; // TEMPORARY FOR TESTING ASYNC RPCs -- CAF @@ -55,7 +55,7 @@ void ASYNC_RPC_REQUEST::clear() { event = NULL; eventHandler = NULL; completionTime = NULL; - result = NULL; + resultPtr = NULL; isActive = false; } @@ -74,7 +74,7 @@ bool ASYNC_RPC_REQUEST::isSameAs(ASYNC_RPC_REQUEST& otherRequest) { } if (eventHandler != otherRequest.eventHandler) return false; if (completionTime != otherRequest.completionTime) return false; - if (result != otherRequest.result) return false; + if (resultPtr != otherRequest.resultPtr) return false; // OK if isActive doesn't match. return true; } @@ -126,6 +126,7 @@ void RPCThread::OnExit() { void *RPCThread::Entry() { int retval; + CRPCFinishedEvent RPC_done_event( wxEVT_RPC_FINISHED ); while(true) { // check if we were asked to exit @@ -145,9 +146,7 @@ void *RPCThread::Entry() { retval = ProcessRPCRequest(); - CRPCFinishedEvent RPC_done_event( wxEVT_RPC_FINISHED ); - RPC_done_event.SetInt(retval); - +// RPC_done_event.SetInt(retval); wxPostEvent( wxTheApp, RPC_done_event ); } @@ -372,11 +371,15 @@ int RPCThread::ProcessRPCRequest() { #if USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS m_Doc->m_critsect.Enter(); + current_request->retval = retval; current_request->isActive = false; + m_Doc->m_critsect.Leave(); #else // Deactivation is an atomic operation + current_request->retval = retval; current_request->isActive = false; + #endif return retval; @@ -401,8 +404,8 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) { if (iter->isSameAs(request)) return 0; } - if ((request.event == NULL) && (request.result == NULL)) { - request.result = &retval; + if ((request.event == NULL) && (request.resultPtr == NULL)) { + request.resultPtr = &retval; } if (hasPriority) { @@ -456,8 +459,24 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) { m_RPCWaitDlg = new AsyncRPCDlg(); do { -// ::wxSafeYield(pFrame, true); // Continue processing events +#if 0 // Yield allows user activity which can cause problems with long values of RPC_WAIT_DLG_DELAY wxTheApp->Yield(true); // Continue processing events + // wxSafeYield prevents user activity but causes ugly disabling of coontrols +// ::wxSafeYield(pFrame, true); // Continue processing events +#else // Simulate handling of CRPCFinishedEvent but don't allow any other events (so no user activity) +// usleep(1); ///// ???? SwitchToThread() on Windows? nanosleep() on UNIX ???? +#ifdef __WXMSW__ + SwitchToThread(); +#else + // TODO: is there a way for main UNIX thread to yield wih no minimum delay? + timespec ts = {0, 1}; /// 1 nanosecond + nanosleep(&ts, NULL); /// 1 nanosecond or less + ///// ???? SwitchToThread() on Windows? nanosleep() on UNIX ???? +#endif + if (!current_rpc_request.isActive) { + HandleCompletedRPC(); + } +#endif // OnRPCComplete() clears m_bWaitingForRPC if RPC completed if (! m_bWaitingForRPC) { // inUserRequest = false; @@ -522,11 +541,23 @@ int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority) { void CMainDocument::OnRPCComplete(CRPCFinishedEvent& event) { - int retval = event.GetInt(); + HandleCompletedRPC(); + return; + } + + void CMainDocument::HandleCompletedRPC() { + int retval; int i, n; std::vector completed_RPC_requests; bool stillWaitingForPendingRequests = false; - + + if(current_rpc_request.isActive) return; + // We can get here either via a CRPCFinishedEvent event posted + // by the RPC thread or by a call from RequestRPC. If we were + // called from RequestRPC, the CRPCFinishedEvent will still be + // on the event queue, so we get called twice. Check for this here. + if (current_rpc_request.which_rpc == 0) return; // already handled by a call from RequestRPC + // Move all requests for the completed RPC to our local vector // We do this in reverse order so we can remove them from queue n = RPC_requests.size(); @@ -541,7 +572,8 @@ void CMainDocument::OnRPCComplete(CRPCFinishedEvent& event) { } } } - + + retval = current_rpc_request.retval; current_rpc_request.clear(); // Start the next RPC request while we process the one just completed. @@ -565,8 +597,8 @@ void CMainDocument::OnRPCComplete(CRPCFinishedEvent& event) { if (completed_RPC_requests[i].completionTime) { *(completed_RPC_requests[i].completionTime) = wxDateTime::Now(); } - if (completed_RPC_requests[i].result) { - *(completed_RPC_requests[i].result) = retval; + if (completed_RPC_requests[i].resultPtr) { + *(completed_RPC_requests[i].resultPtr) = retval; } #if 1 // Post-processing @@ -827,7 +859,7 @@ void CMainDocument::TestAsyncRPC() { // TEMPORARY FOR TESTING ASYNC RPCs request.eventHandler = NULL; request.completionTime = &completionTime; // request.result = NULL; - request.result = &m_iGet_state_RPC_retval; // TEMPORARY FOR TESTING ASYNC RPCs -- CAF + request.resultPtr = &m_iGet_state_RPC_retval; // TEMPORARY FOR TESTING ASYNC RPCs -- CAF request.isActive = false; //retval = rpcClient.get_all_projects_list(pl); diff --git a/clientgui/AsyncRPC.h b/clientgui/AsyncRPC.h index d1633df1b9..fc1b771d54 100644 --- a/clientgui/AsyncRPC.h +++ b/clientgui/AsyncRPC.h @@ -104,7 +104,8 @@ struct ASYNC_RPC_REQUEST { wxEvent *event; wxEvtHandler *eventHandler; wxDateTime *completionTime; - int *result; + int *resultPtr; + int retval; bool isActive; ASYNC_RPC_REQUEST(); diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index a386e74b8a..39cd4218e7 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -580,6 +580,7 @@ int CMainDocument::FrameShutdownDetected() { int CMainDocument::GetCoreClientStatus(CC_STATUS& ccs, bool bForce) { wxString strMachine = wxEmptyString; int iRetVal = 0; + if (IsConnected()) { if (bForce) { m_dtCachedCCStatusTimestamp = wxDateTime::Now(); @@ -671,7 +672,7 @@ void CMainDocument::RunPeriodicRPCs() { request.exchangeBuf = &status; request.event = (wxEvent*)-1; request.completionTime = &m_dtCachedCCStatusTimestamp; - request.result = &cc_status_rpc_result; + request.resultPtr = &cc_status_rpc_result; RequestRPC(request); } @@ -686,7 +687,7 @@ void CMainDocument::RunPeriodicRPCs() { request.arg1 = &state_altbuf; request.exchangeBuf = &state; request.event = (wxEvent*)-1; - request.result = &cc_state_rpc_result; + request.resultPtr = &cc_state_rpc_result; RequestRPC(request); @@ -698,7 +699,7 @@ void CMainDocument::RunPeriodicRPCs() { request.exchangeBuf = &host; request.event = (wxEvent*)-1; request.completionTime = &m_dtCachedStateTimestamp; - request.result = &host_info_rpc_result; + request.resultPtr = &host_info_rpc_result; RequestRPC(request); } diff --git a/clientgui/MainDocument.h b/clientgui/MainDocument.h index ce5c67e47d..c2bd5fb90d 100644 --- a/clientgui/MainDocument.h +++ b/clientgui/MainDocument.h @@ -144,7 +144,6 @@ public: bool IsConnected(); bool IsReconnecting(); - int GetCoreClientStatus(CC_STATUS&, bool bForce = false); int SetActivityRunMode(int iMode, int iTimeout); int SetNetworkRunMode(int iMode, int iTimeout); @@ -176,6 +175,7 @@ public: public: int RequestRPC(ASYNC_RPC_REQUEST& request, bool hasPriority = false); void OnRPCComplete(CRPCFinishedEvent& event); + void HandleCompletedRPC(); ASYNC_RPC_REQUEST* GetCurrentRPCRequest() { return ¤t_rpc_request; }; void TestAsyncRPC(); // TEMPORARY -- CAF RPCThread* m_RPCThread;