Skip to content

Commit

Permalink
Refs #4803 test for MonitorLiveData not allowing overwriting
Browse files Browse the repository at this point in the history
of the same workspace from separate threads. Also, lock in FakeEventDataListener refs #4812
  • Loading branch information
Janik Zikovsky committed Mar 2, 2012
1 parent a616133 commit 202023b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 28 deletions.
10 changes: 8 additions & 2 deletions Code/Mantid/Framework/DataHandling/src/FakeEventDataListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidKernel/MersenneTwister.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/WriteLock.h"

using namespace Mantid::Kernel;
using namespace Mantid::API;
Expand Down Expand Up @@ -81,9 +82,13 @@ namespace DataHandling

// Safety considerations suggest I should stop the thread here, but the below methods don't
// seem to do what I'd expect and I haven't seen any problems from not having them (yet).
//m_timer.stop();
// m_timer.stop();

// Get an exclusive lock to the buffer workspace
// will wait for generateEvents() to finish before swapping
WriteLock _lock(*m_buffer);
std::swap(m_buffer,temp);
//m_timer.restart();
// m_timer.restart();

return temp;
}
Expand All @@ -93,6 +98,7 @@ namespace DataHandling
*/
void FakeEventDataListener::generateEvents(Poco::Timer&)
{
WriteLock _lock(*m_buffer);
for (long i = 0; i < m_callbackloop; ++i)
{
m_buffer->getEventList(0).addEventQuickly(DataObjects::TofEvent(m_rand->next()));
Expand Down
4 changes: 3 additions & 1 deletion Code/Mantid/Framework/DataHandling/src/MonitorLiveData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ namespace DataHandling
for (; it != AlgorithmManager::Instance().algorithms().end(); it++)
{
IAlgorithm_sptr alg = *it;
if (alg->name() == "MonitorLiveData" && (alg->getAlgorithmID() != this->getAlgorithmID()))
// MonitorLiveData thread that is running, except THIS one.
if (alg->name() == "MonitorLiveData" && (alg->getAlgorithmID() != this->getAlgorithmID())
&& alg->isRunning())
{
if (!accumName.empty() && alg->getPropertyValue("AccumulationWorkspace") == accumName)
throw std::runtime_error("Another MonitorLiveData thread is running with the same AccumulationWorkspace. "
Expand Down
101 changes: 76 additions & 25 deletions Code/Mantid/Framework/DataHandling/test/MonitorLiveDataTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iomanip>

#include "MantidDataHandling/MonitorLiveData.h"
#include "MantidAPI/AlgorithmManager.h"

using namespace Mantid;
using namespace Mantid::DataHandling;
Expand All @@ -28,34 +29,84 @@ class MonitorLiveDataTest : public CxxTest::TestSuite
TS_ASSERT_THROWS_NOTHING( alg.initialize() )
TS_ASSERT( alg.isInitialized() )
}


// void test_exec()
// {
// // Name of the output workspace.
// std::string outWSName("MonitorLiveDataTest_OutputWS");
//
// MonitorLiveData alg;
// TS_ASSERT_THROWS_NOTHING( alg.initialize() )
// TS_ASSERT( alg.isInitialized() )
// TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("REPLACE_PROPERTY_NAME_HERE!!!!", "value") );
// TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) );
// TS_ASSERT_THROWS_NOTHING( alg.execute(); );
// TS_ASSERT( alg.isExecuted() );
//
// // Retrieve the workspace from data service. TODO: Change to your desired type
// Workspace_sptr ws;
// TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS<Workspace>(outWSName) );
// TS_ASSERT(ws);
// if (!ws) return;
//
// // TODO: Check the results
//
// // Remove workspace from the data service.
// AnalysisDataService::Instance().remove(outWSName);
// }
/** Create but don't start a MonitorLiveData thread */
IAlgorithm_sptr makeAlgo(std::string output, std::string accum="")
{
IAlgorithm_sptr alg = AlgorithmManager::Instance().create("MonitorLiveData");
alg->setPropertyValue("Instrument", "TestDataListener");
alg->setPropertyValue("UpdateEvery", "1");
alg->setPropertyValue("AccumulationMethod", "Replace");
alg->setPropertyValue("AccumulationWorkspace", accum);
alg->setPropertyValue("OutputWorkspace", output);
return alg;
}

void test_Something()
/** Create and run the algorithm asynchronously */
void test_runAsync()
{
IAlgorithm_sptr alg = makeAlgo("fake1");
Poco::ActiveResult<bool> res1 = alg->executeAsync();
Poco::Thread::sleep(100); // give it some time to start

// Abort the thread.
alg->cancel();
res1.wait(10000);
//TS_ASSERT( AnalysisDataService::Instance().doesExist("fake1") );
}

/** Disallow if you detect another MonitorLiveData thread with the same */
void test_DontAllowTwoAlgorithmsWithSameOutput()
{
IAlgorithm_sptr alg1 = makeAlgo("fake1");
Poco::ActiveResult<bool> res1 = alg1->executeAsync();
Poco::Thread::sleep(100); // give it some time to start

// This algorithm dies because another thread has the same output
IAlgorithm_sptr alg2 = makeAlgo("fake1");
alg2->execute();
TS_ASSERT( !alg2->isExecuted() );

// Abort the thread.
alg1->cancel();
res1.wait(10000);
}

/** Disallow if you detect another MonitorLiveData thread with the AccumulationWorkspace name */
void test_DontAllowTwoAlgorithmsWithSameAccumulationWorkspace()
{
IAlgorithm_sptr alg1 = makeAlgo("fake1", "accum1");
Poco::ActiveResult<bool> res1 = alg1->executeAsync();
Poco::Thread::sleep(100); // give it some time to start

// This algorithm dies because another thread has the same output
IAlgorithm_sptr alg2 = makeAlgo("fake2", "accum1");
alg2->execute();
TS_ASSERT( !alg2->isExecuted() );

// Abort the thread.
alg1->cancel();
res1.wait(10000);
}

/** Disallow if you detect another MonitorLiveData thread with the same */
void test_Allow_AnotherAlgo_IfTheOtherIsFinished()
{
// Start and stop one algorithm
IAlgorithm_sptr alg1 = makeAlgo("fake1");
Poco::ActiveResult<bool> res1 = alg1->executeAsync();
Poco::Thread::sleep(100); // give it some time to start
alg1->cancel();
res1.wait(10000);

// This algorithm if OK because the other is not still running
IAlgorithm_sptr alg2 = makeAlgo("fake1");
Poco::ActiveResult<bool> res2 = alg2->executeAsync();
Poco::Thread::sleep(100); // give it some time to start
TS_ASSERT( alg2->isRunning() );
alg2->cancel();
res2.wait(10000);
}


Expand Down

0 comments on commit 202023b

Please sign in to comment.