NCBI C++ ToolKit
async_call.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: async_call.cpp 43747 2019-08-28 15:41:08Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Roman Katargin
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 
32 #include <corelib/ncbistd.hpp>
33 
40 
41 #include <wx/utils.h>
42 #include <wx/dialog.h>
43 #include <wx/timer.h>
44 #include <wx/sizer.h>
45 #include <wx/stattext.h>
46 #include <wx/button.h>
47 #include <wx/thread.h>
48 #include <wx/app.h>
49 #include <wx/evtloop.h>
50 
52 
53 bool GUI_AsyncExecUnit(IExecuteUnit& exec_unit, const wxString& msg)
54 {
55  return GUI_AsyncExec([&exec_unit](ICanceled& canceled) { return exec_unit.Execute(canceled); }, msg);
56 }
57 
58 void GUI_AsyncJoinFuture(const job_future_base& future, const string& msg)
59 {
60  GUI_AsyncExec([&future](ICanceled&) { while (future.IsRunning()) ::wxMilliSleep(10); }, msg);
61 }
62 
63 class CAsyncCallDlg : public wxDialog
64 {
65 public:
66  CAsyncCallDlg(wxWindow* parent, CAsyncCall::Call& call, int jobId);
67  bool Create(wxWindow* parent);
68  void CreateControls();
69 
70  DECLARE_EVENT_TABLE()
71 
72  void OnTimer(wxTimerEvent& event);
73  void OnCancelClick(wxCommandEvent& event);
74 
75 private:
77  int m_JobId;
78 
79  wxTimer m_Timer;
80 
81  enum {
82  ID_STATIC_TEXT = 10001,
85  };
86 
88  wxButton* m_CancelBtn;
89 };
90 
91 class CExecJob : public CObject, public IAppJob
92 {
93 public:
95  : m_Call(call) {}
96  ~CExecJob();
97  virtual EJobState Run();
99  virtual CRef<CObject> GetResult() { return CRef<CObject>(); }
101  virtual string GetDescr() const { return NcbiEmptyString; }
102  virtual void RequestCancel() { m_Call->RequestCancel(); }
103  virtual bool IsCanceled() const { return m_Call->IsCanceled(); }
104 
105  void Finish();
106 
107 private:
109 
110  std::exception_ptr m_Exception;
111 };
112 
114 {
115  try {
116  m_Call->Execute();
117  return eCompleted;
118  }
119  catch (const std::exception&) {
120  m_Exception = std::current_exception();
121  }
122  return eFailed;
123 }
124 
126 {
127 }
128 
130 {
131  if (m_Exception)
132  std::rethrow_exception(m_Exception);
133 }
134 
135 
137 : m_Call(call), m_JobId(CAppJobDispatcher::eInvalidJobID)
138 {
139 }
140 
141 static bool fInsideAsyncCall = false;
142 
144 {
145  return fInsideAsyncCall;
146 }
147 
148 namespace {
149  class CAsyncCallEventLoop : public wxGUIEventLoop
150  {
151  public:
152  CAsyncCallEventLoop(int JobId) : m_JobId(JobId), m_TopWnd() {}
153  virtual int Run();
154  wxWindow* GetTopWnd() { return m_TopWnd; }
155  private:
156  int m_JobId;
157  wxWindow* m_TopWnd;
158  };
159 } // namespace
160 
162 {
164  wxEventLoopActivator activate(this);
165 
166  size_t count = 100;
167  while(count--) {
168  wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
169  while (node) {
170  wxTopLevelWindow* win = dynamic_cast<wxTopLevelWindow*>(node->GetData());
171  if (win && win->IsActive()) {
172  m_TopWnd = win;
173  break;
174  }
175  node = node->GetNext();
176  }
177 
178  IAppJob::EJobState state = disp.GetJobState(m_JobId);
180  return 1;
181 
182  if (m_TopWnd)
183  break;
184 
185  if (Pending())
186  Dispatch();
187  else
188  ::wxMilliSleep(10);
189  }
190 
191  return 0;
192 }
193 
195 {
196  if( !::wxIsMainThread() ){
197  m_Call.Execute();
198  return;
199  }
200 
201  if (fInsideAsyncCall)
202  return;
204 
205  CRef<CExecJob> job = CRef<CExecJob>( new CExecJob( &m_Call ) );
206 
208  m_JobId = disp.StartJob( *job, "ObjManagerEngineAsyncCall" );
210  return;
211  }
212 
213  for( unsigned long misec = 0; misec < 1000; misec=misec*2+1 ){
214  ::wxMilliSleep( misec ); // in case of 0 it works like Yield()
215 
218  //LOG_POST( Trace << "UI waiting job is finished by " << misec << " ms step." );
219  job->Finish();
220  return;
221  }
222  }
223 
224  CAsyncCallEventLoop loop(m_JobId);
225  if (loop.Run()) {
226  job->Finish();
227  return;
228  }
229 
230  CAsyncCallDlg(loop.GetTopWnd(), m_Call, m_JobId).ShowModal();
231  job->Finish();
232 }
233 
235 {
236  CAsyncCall asyncCall(call);
237  asyncCall.Execute();
238 }
239 
241 {
244  }
245 }
246 
247 BEGIN_EVENT_TABLE( CAsyncCallDlg, wxDialog )
248  EVT_TIMER(-1, CAsyncCallDlg::OnTimer)
249  EVT_BUTTON( ID_BUTTON_CANCEL, CAsyncCallDlg::OnCancelClick)
251 
252 CAsyncCallDlg::CAsyncCallDlg(wxWindow* parent, CAsyncCall::Call& call, int jobId)
253 : m_Call(call), m_JobId(jobId), m_Timer(this), m_ProgressInd(), m_CancelBtn()
254 {
255  Create(parent);
256 }
257 
258 bool CAsyncCallDlg::Create(wxWindow* parent)
259 {
260  long style = 0;
261  parent = GetParentForModalDialog(parent, style);
262 
263  wxDialog::Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, style);
264  SetBackgroundColour(wxColor(wxT("#FFE793")));
265 
266  CreateControls();
267  m_Timer.Start(300);
268 
269  if (GetSizer())
270  {
271  GetSizer()->SetSizeHints(this);
272  }
273 
274  //Centre();
275 
276  wxRect parentRect = parent->GetScreenRect();
277  wxRect rect = GetScreenRect();
278  Move(parentRect.GetRight() - rect.GetWidth() - 2, parentRect.GetBottom() - rect.GetHeight() - 2);
279 
280  return true;
281 }
282 
284 {
285  CAsyncCallDlg* itemDialog1 = this;
286  wxBoxSizer* itemBoxSizer1 = new wxBoxSizer(wxVERTICAL);
287  itemDialog1->SetSizer(itemBoxSizer1, true);
288  wxStaticText* itemStaticText3 = new wxStaticText(itemDialog1, ID_STATIC_TEXT, m_Call.GetDescr(), wxDefaultPosition, wxDefaultSize, 0);
289  wxFont bold(wxNORMAL_FONT->GetPointSize(), wxNORMAL_FONT->GetFamily(), wxNORMAL_FONT->GetStyle(), wxFONTWEIGHT_BOLD, wxNORMAL_FONT->GetUnderlined(), wxNORMAL_FONT->GetFaceName());
290  itemStaticText3->SetFont(bold);
291  itemStaticText3->SetForegroundColour(*wxBLACK);
292  itemBoxSizer1->Add(itemStaticText3, 0, wxALIGN_LEFT|wxTOP|wxLEFT|wxRIGHT, 5);
293 
294  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
295  itemBoxSizer1->Add(itemBoxSizer2);
296 
297  m_ProgressInd = new CIndProgressBar(itemDialog1, ID_PROGRESS_IND, wxDefaultPosition, (m_Call.IsCancalable() ? 160 : 240));
298  itemBoxSizer2->Add(m_ProgressInd, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
299 
300  m_CancelBtn = new wxButton(itemDialog1, ID_BUTTON_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize);
301  itemBoxSizer2->Add(m_CancelBtn, 0, wxALIGN_LEFT | wxALL, 5);
302 
303  if (m_Call.IsCancalable())
304  m_CancelBtn->SetFocus();
305  else
306  m_CancelBtn->Show(false);
307 }
308 
309 void CAsyncCallDlg::OnTimer(wxTimerEvent&)
310 {
311  if (m_Call.IsCancalable() && !m_CancelBtn->IsShown()) {
312  wxPoint posOld = GetPosition() + GetSize();
313 
314  int w, h;
315  m_ProgressInd->GetSize(&w, &h);
316  wxSize size(160, h);
317  m_ProgressInd->SetMinSize(size);
318  m_ProgressInd->SetSize(size);
319 
320  m_CancelBtn->Show();
321  m_CancelBtn->SetFocus();
322  Fit();
323  Move(posOld - GetSize());
324  }
325 
329  m_Timer.Stop();
330  EndModal(wxID_CANCEL);
331  }
332 }
333 
334 void CAsyncCallDlg::OnCancelClick(wxCommandEvent&)
335 {
337  disp.CancelJob(m_JobId);
338  FindWindow(ID_BUTTON_CANCEL)->Enable(false);
339 }
340 
static bool fInsideAsyncCall
Definition: async_call.cpp:141
bool GUI_AsyncExecUnit(IExecuteUnit &exec_unit, const wxString &msg)
Definition: async_call.cpp:53
void GUI_AsyncJoinFuture(const job_future_base &future, const string &msg)
Definition: async_call.cpp:58
std::invoke_result< _Fty, ICanceled & >::type GUI_AsyncExec(_Fty &&_Fnarg, const wxString &msg=wxT("Accessing network..."))
Definition: async_call.hpp:130
CAppJobDispatcher.
wxTimer m_Timer
Definition: async_call.cpp:79
void CreateControls()
Definition: async_call.cpp:283
wxButton * m_CancelBtn
Definition: async_call.cpp:88
CAsyncCall::Call & m_Call
Definition: async_call.cpp:76
bool Create(wxWindow *parent)
Definition: async_call.cpp:258
CIndProgressBar * m_ProgressInd
Definition: async_call.cpp:87
void OnTimer(wxTimerEvent &event)
Definition: async_call.cpp:309
CAsyncCallDlg(wxWindow *parent, CAsyncCall::Call &call, int jobId)
Definition: async_call.cpp:252
void OnCancelClick(wxCommandEvent &event)
Definition: async_call.cpp:334
virtual bool IsCanceled() const
Definition: async_call.hpp:78
void RequestCancel()
Definition: async_call.hpp:74
wxString GetDescr() const
Definition: async_call.hpp:70
virtual void Execute()=0
bool IsCancalable() const
Definition: async_call.hpp:75
Class for GUI asyncronous execition.
Definition: async_call.hpp:61
CAsyncCall(Call &call)
Definition: async_call.cpp:136
void Execute()
Definition: async_call.cpp:194
Call & m_Call
Definition: async_call.hpp:99
static bool InsideAsyncCall()
Definition: async_call.cpp:143
CExecJob(CAsyncCall::Call *call)
Definition: async_call.cpp:94
virtual EJobState Run()
Function that does all the useful work, called by the Engine.
Definition: async_call.cpp:113
virtual CConstIRef< IAppJobError > GetError()
Returns IAppJobError object describing internal error that caused the Job to fail.
Definition: async_call.cpp:100
std::exception_ptr m_Exception
Definition: async_call.cpp:110
virtual CRef< CObject > GetResult()
Returns the Job Result.
Definition: async_call.cpp:99
CAsyncCall::Call * m_Call
Definition: async_call.cpp:108
virtual bool IsCanceled() const
Definition: async_call.cpp:103
void Finish()
Definition: async_call.cpp:129
virtual string GetDescr() const
Returns a human readable description of the Job (optional)
Definition: async_call.cpp:101
virtual void RequestCancel()
RequestCancel() is called to notify the Job that it shall exit Run() function ASAP.
Definition: async_call.cpp:102
virtual CConstIRef< IAppJobProgress > GetProgress()
return progress object, the function shall be synchronized internally.
Definition: async_call.cpp:98
CObject –.
Definition: ncbiobj.hpp:180
IAppJob.
Definition: app_job.hpp:82
Interface for testing cancellation request in a long lasting operation.
Definition: icanceled.hpp:51
virtual bool Execute(ICanceled &canceled)=0
bool IsRunning() const
Definition: job_future.hpp:204
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define _(proto)
Definition: ct_nlmzip_i.h:78
static CAppJobDispatcher & GetInstance()
bool DeleteJob(TJobID job_id)
when a Job is deleted the listener is not notified
EJobState
Job states (describe FSM)
Definition: app_job.hpp:86
TJobID StartJob(IAppJob &job, const string &engine_name, IEngineParams *params=NULL)
Starts a Job on the specified engine in "passive mode" - no notifications or progress reports will be...
TJobState GetJobState(TJobID job_id)
All Get() functions return values stored in the Registy not the actual.
void CancelJob(TJobID job_id)
@ eCompleted
Definition: app_job.hpp:89
@ eRunning
Definition: app_job.hpp:88
@ eSuspended
Definition: app_job.hpp:92
@ eFailed
Definition: app_job.hpp:90
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NcbiEmptyString
Definition: ncbistr.hpp:122
void Run(void)
Enter the main loop.
END_EVENT_TABLE()
#define wxT(x)
Definition: muParser.cpp:41
const struct ncbi::grid::netcache::search::fields::SIZE size
static static static wxID_ANY
wxRect GetScreenRect(const wxWindow &win)
Definition: wx_utils.cpp:783
Modified on Wed Apr 17 13:09:46 2024 by modify_doxy.py rev. 669887