Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/AlgorithmProxy.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/AlgorithmObserver.h"
#include <iostream>
using namespace Mantid::Kernel;
namespace Mantid
{
namespace API
{
// Get a reference to the logger
Kernel::Logger& AlgorithmProxy::g_log = Kernel::Logger::get("AlgorithmProxyProxy");
//----------------------------------------------------------------------
// Public methods
//----------------------------------------------------------------------
/// Constructor
AlgorithmProxy::AlgorithmProxy(IAlgorithm_sptr alg) :
PropertyManagerOwner(),_executeAsync(this,&AlgorithmProxy::executeAsyncImpl),
m_name(alg->name()),m_category(alg->category()),m_version(alg->version()),m_isExecuted(),m_isLoggingEnabled(true)
{
Algorithm_sptr a = boost::dynamic_pointer_cast<Algorithm>(alg);
if (!a)
{
g_log.error("Unable to create a proxy algorithm.");
throw std::logic_error("Unable to create a proxy algorithm.");
}
a->initialize();
copyPropertiesFrom(*a);
}
/// Virtual destructor
AlgorithmProxy::~AlgorithmProxy()
{
}
/** Initialization method invoked by the framework. This method is responsible
* for any bookkeeping of initialization required by the framework itself.
* It will in turn invoke the init() method of the derived AlgorithmProxy,
* and of any sub-AlgorithmProxys which it creates.
* @throw runtime_error Thrown if AlgorithmProxy or sub-AlgorithmProxy cannot be initialised
*
*/
void AlgorithmProxy::initialize()
{
// Do nothing as initialization is done in the constructor
return;
}
/** The actions to be performed by the AlgorithmProxy on a dataset. This method is
* invoked for top level AlgorithmProxys by the application manager.
* This method invokes exec() method.
* For sub-AlgorithmProxys either the execute() method or exec() method
* must be EXPLICITLY invoked by the parent AlgorithmProxy.
*
* @throw runtime_error Thrown if AlgorithmProxy or sub-AlgorithmProxy cannot be executed
*/
bool AlgorithmProxy::execute()
{
m_alg = boost::dynamic_pointer_cast<Algorithm>(AlgorithmManager::Instance().createUnmanaged(name(),version()));
m_alg->initializeFromProxy(*this);
addObservers();
try
{
m_alg->execute();
}
catch(...)
{
// zero the pointer and rethrow
m_alg.reset();
throw;
}
m_isExecuted = m_alg->isExecuted();
m_alg.reset();
return m_isExecuted;
}
/// True if the algorithm is running asynchronously.
bool AlgorithmProxy::isRunningAsync()
{
return m_alg? m_alg->isRunningAsync():false;
}
/// True if the algorithm is running.
bool AlgorithmProxy::isRunning()
{
return m_alg? m_alg->isRunning():false;
}
/// Has the AlgorithmProxy already been initialized
bool AlgorithmProxy::isInitialized() const
{
return true;//!!!!!!!!!
}
/// Has the AlgorithmProxy already been executed
bool AlgorithmProxy::isExecuted() const
{
return m_isExecuted;
}
void AlgorithmProxy::cancel()const
{
if (m_alg)
m_alg->cancel();
}
/** Add an observer for a notification. If the real algorithm is running
the observer is added directly. If the algorithm is not running yet
the observer's address is added to a buffer to be used later when execute/executeAsync
method is called.
@param observer Observer
*/
void AlgorithmProxy::addObserver(const Poco::AbstractObserver& observer)const
{
const Poco::AbstractObserver* obs = &observer;
if (m_alg)
{
m_alg->addObserver(*obs);
}
else
m_externalObservers.push_back(obs);
}
/** Remove an observer.
@param observer Observer
*/
void AlgorithmProxy::removeObserver(const Poco::AbstractObserver& observer)const
{
std::vector<const Poco::AbstractObserver*>::iterator o =
std::find(m_externalObservers.begin(),m_externalObservers.end(),&observer);
if (o != m_externalObservers.end()) m_externalObservers.erase(o);
if (m_alg) m_alg->removeObserver(observer);
}
//----------------------------------------------------------------------
// Private methods
//----------------------------------------------------------------------
/**
* Clean up when the real algorithm stops
*/
void AlgorithmProxy::stopped()
{
m_isExecuted = m_alg->isExecuted();
}
/**
* Add observers stored previously in m_externalObservers
*/
void AlgorithmProxy::addObservers()
{
if (!m_alg) return;
std::vector<const Poco::AbstractObserver*>::reverse_iterator o = m_externalObservers.rbegin();
for(;o != m_externalObservers.rend();o++)
m_alg->addObserver(**o);
m_externalObservers.clear();
}
/**
* executeAsync() implementation. Calls execute and when it has finished deletes the real algorithm.
*/
bool AlgorithmProxy::executeAsyncImpl(const Poco::Void &)
{
m_alg = boost::dynamic_pointer_cast<Algorithm>(AlgorithmManager::Instance().createUnmanaged(name(),version()));
m_alg->initializeFromProxy(*this);
addObservers();
Poco::ActiveResult<bool> res = m_alg->executeAsync();
res.wait();
m_isExecuted = m_alg->isExecuted();
m_alg.reset();
try
{
return res.data();
}
catch(Poco::NullPointerException&)
{
return false;
}
}
} // namespace API
} // namespace Mantid