diff --git a/checkin_notes b/checkin_notes index 6e72ba01c0..eec2d099e5 100644 --- a/checkin_notes +++ b/checkin_notes @@ -5845,3 +5845,12 @@ David 17 July 2008 sched/ sched_send.C + +Charlie 18 July 2008 + - MGR: First round of changes for asycn GUI RPCs; includes temporary + changes for testing. + + clientgui/ + AsyncRPC.cpp,.h + BOINCBaseFrame.cpp,.h + MainDocument.cpp,.h diff --git a/clientgui/AsyncRPC.cpp b/clientgui/AsyncRPC.cpp new file mode 100644 index 0000000000..bd068a89b4 --- /dev/null +++ b/clientgui/AsyncRPC.cpp @@ -0,0 +1,407 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma implementation "AsyncRPC.h" +#endif + +#include + +#include "stdwx.h" +//#include "wx/artprov.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "AsyncRPC.h" +//#include "BOINCClientManager.h" + +// Delay in milliseconds before showing AsyncRPCDlg +#define RPC_WAIT_DLG_DELAY 250 + +ASYNC_RPC_REQUEST::ASYNC_RPC_REQUEST() { + clear(); +} + + +ASYNC_RPC_REQUEST::~ASYNC_RPC_REQUEST() { + clear(); +} + + +void ASYNC_RPC_REQUEST::clear() { + which_rpc = (RPC_SELECTOR) 0; + inBuf = NULL; + exchangeBuf = NULL; + outBuf = NULL; + event = NULL; + eventHandler = NULL; + completionTime = NULL; + isActive = false; +} + + +bool ASYNC_RPC_REQUEST::isSameAs(ASYNC_RPC_REQUEST& otherRequest) { + if (which_rpc != otherRequest.which_rpc) return false; + if (inBuf != otherRequest.inBuf) return false; + if (exchangeBuf != otherRequest.exchangeBuf) return false; + if (outBuf != otherRequest.outBuf) return false; + if (event != otherRequest.event) { + if (event->GetEventType() != (otherRequest.event)->GetEventType()) return false; + if (event->GetId() != (otherRequest.event)->GetId()) return false; + if (event->GetEventObject() != (otherRequest.event)->GetEventObject()) return false; + } + if (eventHandler != otherRequest.eventHandler) return false; + if (completionTime != otherRequest.completionTime) return false; + // OK if isActive doesn't match. + return true; +} + + +RPCThread::RPCThread(CMainDocument *pDoc) + : wxThread() { + m_Doc = pDoc; +} + + +void RPCThread::OnExit() { +} + + +// We don't need critical sections because: +// 1. CMainDocument never modifies mDoc->current_rpc_request while the +// async RPC thread is using it. +// 2. The async RPC thread never modifies either mDoc->current_rpc_request +// or the vector of requests mDoc->RPC_requests. + +void *RPCThread::Entry() { + int retval; + + while(true) { + // check if we were asked to exit + if ( TestDestroy() ) + break; + + if (! m_Doc->GetCurrentRPCRequest()->isActive) { + // Wait until CMainDocument issues next RPC request + Yield(); + continue; + } + + retval = ProcessRPCRequest(); + +// TODO: Do we need a critical section here and in CBOINCGUIApp::SetActiveGUI()? + // We need to get the frame each time, in case it was + // changed by a call to CBOINCGUIApp::SetActiveGUI(). + CBOINCBaseFrame* pFrame = wxGetApp().GetFrame(); + wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame)); + + CRPCFinishedEvent RPC_done_event( wxEVT_RPC_FINISHED, pFrame ); + RPC_done_event.SetInt(retval); + + wxPostEvent( pFrame, RPC_done_event ); + } + + return NULL; +} + + +int RPCThread::ProcessRPCRequest() { + int retval = 0; + ASYNC_RPC_REQUEST *current_request; + + current_request = m_Doc->GetCurrentRPCRequest(); + + switch (current_request->which_rpc) { + case RPC_GET_RESULTS: + if (current_request->inBuf == NULL) return -1; + // TODO: Confirm if the following is correct + retval = (m_Doc->rpc).get_results((RESULTS&)*(RESULTS*)(current_request->inBuf)); + break; + case RPC_GET_ALL_PROJECTS_LIST: + if (current_request->inBuf == NULL) return -1; +// Sleep(5000); // TEMPORARY FOR TESTING ASYNC RPCs -- CAF + retval = (m_Doc->rpc).get_all_projects_list((ALL_PROJECTS_LIST&)*(ALL_PROJECTS_LIST*)(current_request->inBuf)); + break; + default: + break; + } + +#if USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS + m_Doc->m_critsect.Enter(); + current_request->isActive = false; + m_Doc->m_critsect.Leave(); +#else + // Deactivation is an atomic operation + current_request->isActive = false; +#endif + + return retval; +} + + +// We don't need critical sections because: +// 1. CMainDocument never modifies mDoc->current_rpc_request while the +// async RPC thread is using it. +// 2. The async RPC thread never modifies either mDoc->current_rpc_request +// or the vector of requests mDoc->RPC_requests. + +// TODO: combine RPC requests for different buffers, then just copy the buffer. + +int CMainDocument::RequestRPC(ASYNC_RPC_REQUEST& request) { + static bool inUserRequest = false; + std::vector::iterator iter; + int retval = 0; + + // Check if a duplicate request is already on the queue + for (iter=RPC_requests.begin(); iter!=RPC_requests.end(); iter++) { + if (iter->isSameAs(request)) return 0; + } + + if (request.event == NULL) { + // If no completion event specified, this is a user-initiated event. + // Since the user is waiting, insert this at head of request queue + iter = RPC_requests.insert(RPC_requests.begin(), request); + } else { + RPC_requests.push_back(request); + } + + // Start this RPC if no other RPC is already in progress. + if (RPC_requests.size() == 1) { +#if USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS + m_critsect.Enter(); + current_rpc_request = request; + current_rpc_request.isActive = true; + m_critsect.Leave(); +#else + // Make sure activation is an atomic operation + request.isActive = false; + current_rpc_request = request; + current_rpc_request.isActive = true; +#endif + } + + // If no completion event specified, this is a user-initiated event so + // wait for completion but show a dialog allowing the user to cancel. + if ((request.event == NULL) && !inUserRequest) { + inUserRequest = true; + // Don't show dialog if RPC completes before RPC_WAIT_DLG_DELAY + wxStopWatch Dlgdelay = wxStopWatch(); + m_RPCWaitDlg = new AsyncRPCDlg(); + do { + // OnRPCComplete() sets m_RPCWaitDlg to NULL if RPC completed + if (! m_RPCWaitDlg) { + inUserRequest = false; + return retval; + } + ::wxSafeYield(NULL, true); // Continue processing events + } while (Dlgdelay.Time() < RPC_WAIT_DLG_DELAY); + +// TODO: ****** Cancel RPC if user pressed Cancel. ******** +// TODO: ****** Because buffer may have been on stack! ******** + if (m_RPCWaitDlg) { + // GetCurrentProcess(&psn); + // SetFrontProcess(&psn); // Shows process if hidden + if (m_RPCWaitDlg->ShowModal() != wxID_OK) retval = -1; + if (m_RPCWaitDlg) + m_RPCWaitDlg->Destroy(); + m_RPCWaitDlg = NULL; + } + inUserRequest = false; + } + + return retval; +} + + +void CMainDocument::OnRPCComplete(CRPCFinishedEvent& event) { + int retval = event.GetInt(); + int i, n; + std::vector completed_RPC_requests; + + // 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(); + for (i=n-1; i>=0; --i) { + if (RPC_requests[i].which_rpc == current_rpc_request.which_rpc) { + completed_RPC_requests.push_back(RPC_requests[i]); + RPC_requests[i].event = NULL; // Is this needed to prevent calling event's destructor? + RPC_requests.erase(RPC_requests.begin()+i); + + } + } + + current_rpc_request.clear(); + + // Start the next RPC request while we process the one just completed. + if (RPC_requests.size() > 0) { +#if USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS + m_critsect.Enter(); + current_rpc_request = RPC_requests[0]; + current_rpc_request.isActive = true; + m_critsect.Leave(); +#else + // Make sure activation is an atomic operation + RPC_requests[0].isActive = false; + current_rpc_request = RPC_requests[0]; + current_rpc_request.isActive = true; +#endif + } + + // Now process the requests we have satisfied. + n = completed_RPC_requests.size(); + for (i=n-1; i>=0; --i) { + if (completed_RPC_requests[i].completionTime) { + *(completed_RPC_requests[i].completionTime) = wxDateTime::Now(); + } + + switch (completed_RPC_requests[i].which_rpc) { + case RPC_GET_RESULTS: + m_iGet_results_RPC_retval = retval; + if (completed_RPC_requests[i].exchangeBuf) { + RESULTS* inBuf = (RESULTS*)completed_RPC_requests[i].inBuf; + RESULTS* exchangeBuf = (RESULTS*)completed_RPC_requests[i].exchangeBuf; + inBuf->results.swap(exchangeBuf->results); + } + break; + case RPC_GET_ALL_PROJECTS_LIST: + m_iGet_results_RPC_retval = retval; + if (completed_RPC_requests[i].exchangeBuf) { + ALL_PROJECTS_LIST* inBuf = (ALL_PROJECTS_LIST*)completed_RPC_requests[i].inBuf; + ALL_PROJECTS_LIST* exchangeBuf = (ALL_PROJECTS_LIST*)completed_RPC_requests[i].exchangeBuf; + inBuf->projects.swap(exchangeBuf->projects); + } + break; + default: + break; + } + + if (completed_RPC_requests[i].event) { + if (completed_RPC_requests[i].eventHandler) { + completed_RPC_requests[i].eventHandler->ProcessEvent(*completed_RPC_requests[i].event); + } else { + CBOINCBaseFrame* pFrame = wxGetApp().GetFrame(); + wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame)); + pFrame->ProcessEvent(*completed_RPC_requests[i].event); + } + delete completed_RPC_requests[i].event; + completed_RPC_requests[i].event = NULL; + } + } + + if (m_RPCWaitDlg) { + if (m_RPCWaitDlg->IsShown()) { + m_RPCWaitDlg->EndModal(wxID_OK); + } else { + m_RPCWaitDlg->Destroy(); + m_RPCWaitDlg = NULL; + } + } +} + + +IMPLEMENT_CLASS(AsyncRPCDlg, wxDialog) + +AsyncRPCDlg::AsyncRPCDlg() : wxDialog( NULL, wxID_ANY, wxT(""), wxDefaultPosition ) { + + wxString message = wxString(_("Communicating with BOINC client. Please wait ...")); + + wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer *icon_text = new wxBoxSizer( wxHORIZONTAL ); + +// wxBitmap bitmap = wxArtProvider::GetIcon(wxART_INFORMATION, wxART_MESSAGE_BOX); +// wxStaticBitmap *icon = new wxStaticBitmap(this, wxID_ANY, bitmap); +// icon_text->Add( icon, 0, wxCENTER ); + + icon_text->Add( CreateTextSizer( message ), 0, wxALIGN_CENTER | wxLEFT, 10 ); + topsizer->Add( icon_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 ); + + int center_flag = wxEXPAND; + wxSizer *sizerBtn = CreateSeparatedButtonSizer(wxCANCEL|wxNO_DEFAULT); + if ( sizerBtn ) + topsizer->Add(sizerBtn, 0, center_flag | wxALL, 10 ); + + SetAutoLayout( true ); + SetSizer( topsizer ); + + topsizer->SetSizeHints( this ); + topsizer->Fit( this ); + wxSize size( GetSize() ); + if (size.x < size.y*3/2) + { + size.x = size.y*3/2; + SetSize( size ); + } + + Centre( wxBOTH | wxCENTER_FRAME); + +#if USE_RPC_DLG_TIMER + m_pDlgDelayTimer = new wxTimer(this, wxID_ANY); + wxASSERT(m_pDlgDelayTimer); + + m_pDlgDelayTimer->Start(100, false); +#endif // USE_RPC_DLG_TIMER +} + + +#if USE_RPC_DLG_TIMER +BEGIN_EVENT_TABLE(AsyncRPCDlg, wxMessageDialog) + EVT_TIMER(wxID_ANY, AsyncRPCDlg::OnRPCDlgTimer) +END_EVENT_TABLE() + +AsyncRPCDlg::~AsyncRPCDlg() { + if (m_pDlgDelayTimer) { + m_pDlgDelayTimer->Stop(); + delete m_pDlgDelayTimer; + m_pDlgDelayTimer = NULL; + } +} + + +void AsyncRPCDlg::OnRPCDlgTimer(wxTimerEvent& WXUNUSED(event)) { + ::wxWakeUpIdle(); +} +#endif // USE_RPC_DLG_TIMER + +/// For testing: triggered by Advanced / Options menu item. +ALL_PROJECTS_LIST pl; + +void CMainDocument::TestAsyncRPC() { // TEMPORARY FOR TESTING ASYNC RPCs -- CAF + ASYNC_RPC_REQUEST request; + wxDateTime completionTime; + int retval = 0; + + completionTime.ResetTime(); + + request.which_rpc = RPC_GET_ALL_PROJECTS_LIST; + request.inBuf = &pl; + request.exchangeBuf = NULL; + request.outBuf = NULL; + request.event = NULL; + request.eventHandler = NULL; + request.completionTime = &completionTime; + request.isActive = false; + +//retval = rpc.get_all_projects_list(pl); + + retval = RequestRPC(request); + + wxString s = completionTime.Format("%T"); + printf("Completion time = %s\n", s.c_str()); + printf("RequestRPC returned %d\n", retval); +} + diff --git a/clientgui/AsyncRPC.h b/clientgui/AsyncRPC.h new file mode 100644 index 0000000000..af1a98461a --- /dev/null +++ b/clientgui/AsyncRPC.h @@ -0,0 +1,165 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef _ASYNCRPC_H_ +#define _ASYNCRPC_H_ + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma interface "AsyncRPC.cpp" +#endif + +#include "wx/thread.h" + +#include "BOINCBaseFrame.h" + +//#include "common_defs.h" +//#include "gui_rpc_client.h" + +#define USE_RPC_DLG_TIMER 0 +#define USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS 0 + +class CMainDocument; // Forward declaration + + +enum RPC_SELECTOR { + RPC_INIT_POLL = 1, + RPC_AUTHORIZE, + RPC_INIT_ASYNCH, + RPC_EXCHANGE_VERSIONS, + RPC_GET_STATE, + RPC_GET_HOST_INFO, + RPC_GET_CC_STATUS, + RPC_GET_PROJECT_STATUS, + RPC_GET_RESULTS, + RPC_GET_MESSAGES, + RPC_GET_FILE_TRANSFERS, + RPC_GET_DISK_USAGE, + RPC_GET_STATISTICS, + RPC_GET_PROXY_SETTINGS, + RPC_GET_SIMPLE_GUI_INFO, + RPC_SET_RUN_MODE, + RPC_SET_NETWORK_MODE, + RPC_RUN_BENCHMARKS, + RPC_QUIT, + RPC_SET_PROXY_SETTINGS, + RPC_PROJECT_OP, + RPC_RESULT_OP, + RPC_SHOW_GRAPHICS, + RPC_FILE_TRANSFER_OP, + RPC_ACCT_MGR_RPC, + RPC_ACCT_MGR_RPC_POLL, + RPC_GET_PROJECT_CONFIG, + RPC_GET_PROJECT_CONFIG_POLL, + RPC_ACCT_MGR_INFO, + RPC_READ_GLOBAL_PREFS_OVERRIDE, + RPC_READ_CC_CONFIG, + RPC_NETWORK_AVAILABLE, + RPC_GET_PROJECT_INIT_STATUS, + RPC_INIT, + RPC_GET_GLOBAL_PREFS_WORKING_STRUCT, + RPC_GET_GLOBAL_PREFS_OVERRIDE_STRUCT, + RPC_SET_GLOBAL_PREFS_OVERRIDE_STRUCT, + RPC_CREATE_ACCOUNT, + RPC_CREATE_ACCOUNT_POLL, + RPC_LOOKUP_ACCOUNT, + RPC_LOOKUP_ACCOUNT_POLL, + RPC_PROJECT_ATTACH, + RPC_PROJECT_ATTACH_FROM_FILE, + RPC_PROJECT_ATTACH_POLL, + RPC_GET_ALL_PROJECTS_LIST +}; + + +struct ASYNC_RPC_REQUEST { + RPC_SELECTOR which_rpc; + void *inBuf; + void *exchangeBuf; + void *outBuf; + wxEvent *event; + wxEvtHandler *eventHandler; + wxDateTime *completionTime; + bool isActive; + + ASYNC_RPC_REQUEST(); + ~ASYNC_RPC_REQUEST(); + + void clear(); + bool isSameAs(ASYNC_RPC_REQUEST& otherRequest); +}; + + +class RPCThread : public wxThread +{ +public: + RPCThread(CMainDocument *pDoc); + virtual void *Entry(); + virtual void OnExit(); + +private: + int ProcessRPCRequest(); + + CMainDocument *m_Doc; +}; + + +class AsyncRPCDlg : public wxDialog +{ + DECLARE_DYNAMIC_CLASS( AsyncRPCDlg ) + +public: + AsyncRPCDlg(); + void OnRPCDlgTimer(wxTimerEvent &event); + +#if USE_RPC_DLG_TIMER + ~AsyncRPCDlg(); +private: + wxTimer* m_pDlgDelayTimer; + + DECLARE_EVENT_TABLE() +#endif // USE_RPC_DLG_TIMER +}; + + +class CRPCFinishedEvent : public wxEvent +{ +public: + CRPCFinishedEvent(wxEventType evtType, CBOINCBaseFrame *pFrame) + : wxEvent(-1, evtType) + { + SetEventObject(pFrame); + } + + virtual wxEvent * Clone() const { return new CRPCFinishedEvent(*this); } + + void SetInt(int i) { m_retval = i; } + int GetInt() const { return m_retval; } +private: + int m_retval; +}; + +BEGIN_DECLARE_EVENT_TYPES() +DECLARE_EVENT_TYPE( wxEVT_RPC_FINISHED, -1 ) +END_DECLARE_EVENT_TYPES() + +#define EVT_RPC_FINISHED(fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_RPC_FINISHED, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), + + + +#endif // _ASYNCRPC_H_ \ No newline at end of file diff --git a/clientgui/BOINCBaseFrame.cpp b/clientgui/BOINCBaseFrame.cpp index ad71e892e0..c77813c7a8 100644 --- a/clientgui/BOINCBaseFrame.cpp +++ b/clientgui/BOINCBaseFrame.cpp @@ -45,6 +45,7 @@ DEFINE_EVENT_TYPE(wxEVT_FRAME_INITIALIZED) DEFINE_EVENT_TYPE(wxEVT_FRAME_REFRESHVIEW) DEFINE_EVENT_TYPE(wxEVT_FRAME_UPDATESTATUS) DEFINE_EVENT_TYPE(wxEVT_FRAME_RELOADSKIN) +DEFINE_EVENT_TYPE(wxEVT_RPC_FINISHED) IMPLEMENT_DYNAMIC_CLASS(CBOINCBaseFrame, wxFrame) @@ -56,6 +57,7 @@ BEGIN_EVENT_TABLE (CBOINCBaseFrame, wxFrame) EVT_FRAME_ALERT(CBOINCBaseFrame::OnAlert) EVT_CLOSE(CBOINCBaseFrame::OnClose) EVT_MENU(ID_FILECLOSEWINDOW, CBOINCBaseFrame::OnCloseWindow) + EVT_RPC_FINISHED(CBOINCBaseFrame::OnRPCFinished) END_EVENT_TABLE () @@ -289,6 +291,16 @@ void CBOINCBaseFrame::OnCloseWindow(wxCommandEvent& WXUNUSED(event)) { } +void CBOINCBaseFrame::OnRPCFinished( CRPCFinishedEvent& event ) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + pDoc->OnRPCComplete(event); +} + + void CBOINCBaseFrame::OnExit(wxCommandEvent& WXUNUSED(event)) { wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnExit - Function Begin")); diff --git a/clientgui/BOINCBaseFrame.h b/clientgui/BOINCBaseFrame.h index b6fb5708ca..5096f1cc2d 100644 --- a/clientgui/BOINCBaseFrame.h +++ b/clientgui/BOINCBaseFrame.h @@ -27,6 +27,7 @@ class CFrameEvent; class CFrameAlertEvent; class CBOINCDialUpManager; +class CRPCFinishedEvent; enum FrameAlertEventType { AlertNormal = 0, @@ -61,6 +62,7 @@ public: virtual void OnClose( wxCloseEvent& event ); virtual void OnCloseWindow( wxCommandEvent& event ); virtual void OnExit( wxCommandEvent& event ); + virtual void OnRPCFinished( CRPCFinishedEvent& event ); int GetReminderFrequency() { return m_iReminderFrequency; } wxString GetDialupConnectionName() { return m_strNetworkDialupConnectionName; } diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index e107a2c2ce..1d3d8d1b85 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -64,7 +64,7 @@ CNetworkConnection::CNetworkConnection(CMainDocument* pDocument) : m_bUsedDefaultPassword = false; m_iPort = GUI_RPC_PORT, m_iReadGUIRPCAuthFailure = 0; -} + } CNetworkConnection::~CNetworkConnection() { @@ -378,6 +378,16 @@ int CMainDocument::OnInit() { m_pClientManager = new CBOINCClientManager(); wxASSERT(m_pClientManager); + m_RPCWaitDlg = NULL; + + m_RPCThread = new RPCThread(this); + wxASSERT(m_RPCThread); + + iRetVal = m_RPCThread->Create(); + wxASSERT(iRetVal); + + m_RPCThread->Run(); + return iRetVal; } @@ -956,6 +966,7 @@ int CMainDocument::CachedResultsStatusUpdate() { m_dtResultsTimestamp = wxDateTime::Now(); iRetVal = rpc.get_results(results); +iRetVal = m_iGet_results_RPC_retval; if (iRetVal) { wxLogTrace(wxT("Function Status"), wxT("CMainDocument::CachedResultsStatusUpdate - Get Result Status Failed '%d'"), iRetVal); ForceCacheUpdate(); diff --git a/clientgui/MainDocument.h b/clientgui/MainDocument.h index 51a9eed836..f66de9c2de 100644 --- a/clientgui/MainDocument.h +++ b/clientgui/MainDocument.h @@ -27,6 +27,7 @@ #include #include "common_defs.h" #include "gui_rpc_client.h" +#include "asyncRPC.h" typedef struct { int slot; @@ -159,6 +160,23 @@ public: HOST_INFO host; wxDateTime m_dtCachedStateTimestamp; + // + // Async RPC support + // +public: + int RequestRPC(ASYNC_RPC_REQUEST& request); + void OnRPCComplete(CRPCFinishedEvent& event); + ASYNC_RPC_REQUEST* GetCurrentRPCRequest() { return ¤t_rpc_request; }; +void TestAsyncRPC(); // TEMPORARY -- CAF +#if USE_CRITICAL_SECTIONS_FOR_ASYNC_RPCS + wxCriticalSection m_critsect; +#endif + +private: + RPCThread* m_RPCThread; + ASYNC_RPC_REQUEST current_rpc_request; + AsyncRPCDlg* m_RPCWaitDlg; + std::vector RPC_requests; // // Project Tab @@ -210,6 +228,8 @@ private: public: RESULTS results; + RESULTS async_results_buf; + int m_iGet_results_RPC_retval; RESULT* result(unsigned int); RESULT* result(const wxString& name, const wxString& project_url);