Newer
Older
//----------------------------------------------------------------------
// 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");
Russell Taylor
committed
//----------------------------------------------------------------------
// Public methods
//----------------------------------------------------------------------
/// Constructor
AlgorithmProxy::AlgorithmProxy(IAlgorithm_sptr alg) :
Russell Taylor
committed
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()
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
/** 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
Roman Tolchenov
committed
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.
Roman Tolchenov
committed
@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);
}
Roman Tolchenov
committed
/** 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);
}
Russell Taylor
committed
//----------------------------------------------------------------------
// Private methods
//----------------------------------------------------------------------
Gigg, Martyn Anthony
committed
/**
Peterson, Peter
committed
* Clean up when the real algorithm stops
Gigg, Martyn Anthony
committed
*/
void AlgorithmProxy::stopped()
{
m_isExecuted = m_alg->isExecuted();
}
Gigg, Martyn Anthony
committed
/**
* 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();
}
Gigg, Martyn Anthony
committed
/**
Peterson, Peter
committed
* executeAsync() implementation. Calls execute and when it has finished deletes the real algorithm.
Gigg, Martyn Anthony
committed
*/
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
{
Roman Tolchenov
committed
return res.data();
Gigg, Martyn Anthony
committed
}
catch(Poco::NullPointerException&)
{
return false;
}
Roman Tolchenov
committed
}
} // namespace API
} // namespace Mantid