Skip to content

Commit

Permalink
Refs #4379: reference to original workspace gets deleted in MDHistoWS
Browse files Browse the repository at this point in the history
when the original workspace is removed from AnalysisDataService. This should allow the destructor to be called properly, freeing memory and closing the file. Should let windows system test pass.
  • Loading branch information
Janik Zikovsky committed Dec 31, 2011
1 parent 78c6444 commit 57fd372
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
15 changes: 12 additions & 3 deletions Code/Mantid/Framework/API/inc/MantidAPI/MDGeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "MantidKernel/Exception.h"
#include "MantidKernel/System.h"
#include "MantidKernel/VMD.h"
#include "MantidAPI/AnalysisDataService.h"
#include <Poco/NObserver.h>


namespace Mantid
Expand Down Expand Up @@ -77,8 +79,8 @@ namespace API

// --------------------------------------------------------------------------------------------
bool hasOriginalWorkspace() const;
boost::shared_ptr<IMDWorkspace> getOriginalWorkspace() const;
void setOriginalWorkspace(boost::shared_ptr<IMDWorkspace> ws);
boost::shared_ptr<Workspace> getOriginalWorkspace() const;
void setOriginalWorkspace(boost::shared_ptr<Workspace> ws);
Mantid::API::CoordTransform * getTransformFromOriginal() const;
void setTransformFromOriginal(Mantid::API::CoordTransform * transform);
Mantid::API::CoordTransform * getTransformToOriginal() const;
Expand All @@ -100,11 +102,15 @@ namespace API


protected:

/// Function called when observer objects recieves a notification
void deleteNotificationReceived(Mantid::API::WorkspaceDeleteNotification_ptr notice);

/// Vector of the dimensions used, in the order X Y Z t, etc.
std::vector<Mantid::Geometry::IMDDimension_sptr> m_dimensions;

/// Pointer to the original workspace, if this workspace is a coordinate transformation from an original workspace.
boost::shared_ptr<IMDWorkspace> m_originalWorkspace;
boost::shared_ptr<Workspace> m_originalWorkspace;

/// Vector of the basis vector (in the original workspace) for each dimension of this workspace.
std::vector<Mantid::Kernel::VMD> m_basisVectors;
Expand All @@ -118,6 +124,9 @@ namespace API
/// Coordinate Transformation that goes from this workspace's coordinates to the original workspace coordinates.
Mantid::API::CoordTransform * m_transformToOriginal;

/// Poco delete notification observer object
Poco::NObserver<MDGeometry, Mantid::API::WorkspaceDeleteNotification> m_delete_observer;


};

Expand Down
35 changes: 32 additions & 3 deletions Code/Mantid/Framework/API/src/MDGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ namespace API
/** Constructor
*/
MDGeometry::MDGeometry()
:m_transformFromOriginal(NULL), m_transformToOriginal(NULL)
:m_transformFromOriginal(NULL), m_transformToOriginal(NULL),
m_delete_observer(*this, &MDGeometry::deleteNotificationReceived)
{
// Watch for workspace deletions
API::AnalysisDataService::Instance().notificationCenter.addObserver(m_delete_observer);
}

//----------------------------------------------------------------------------------------------
Expand All @@ -29,6 +32,8 @@ namespace API
delete m_transformFromOriginal;
if (m_transformToOriginal)
delete m_transformToOriginal;
// Stop watching once object is deleted
API::AnalysisDataService::Instance().notificationCenter.removeObserver(m_delete_observer);
}


Expand Down Expand Up @@ -208,17 +213,41 @@ namespace API
}

/// @return the original workspace to which the basis vectors relate
boost::shared_ptr<IMDWorkspace> MDGeometry::getOriginalWorkspace() const
boost::shared_ptr<Workspace> MDGeometry::getOriginalWorkspace() const
{
return m_originalWorkspace;
}

/// Set the original workspace to which the basis vectors relate
void MDGeometry::setOriginalWorkspace(boost::shared_ptr<IMDWorkspace> ws)
void MDGeometry::setOriginalWorkspace(boost::shared_ptr<Workspace> ws)
{
m_originalWorkspace = ws;
}


//---------------------------------------------------------------------------------------------------
/** Function called when observer objects receives a notification that
* a workspace has been deleted.
*
* This checks if the "original workspace" in this object is being deleted,
* and removes the reference to it to allow it to be destructed properly.
*
* @param notice :: notification of workspace deletion
*/
void MDGeometry::deleteNotificationReceived(Mantid::API::WorkspaceDeleteNotification_ptr notice)
{
if (bool(m_originalWorkspace))
{
// Compare the pointer being deleted to the one stored as the original.
Workspace_sptr deleted = notice->object();
if (this->m_originalWorkspace == deleted)
{
// Clear the reference
m_originalWorkspace.reset();
}
}
}

//---------------------------------------------------------------------------------------------------
/// @return Coordinate Transformation that goes from the original workspace to this workspace's coordinates.
Mantid::API::CoordTransform * MDGeometry::getTransformFromOriginal() const
Expand Down
34 changes: 34 additions & 0 deletions Code/Mantid/Framework/API/test/MDGeometryTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <iostream>
#include "MantidKernel/VMD.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidTestHelpers/FakeObjects.h"

using namespace Mantid;
using namespace Mantid::Kernel;
Expand Down Expand Up @@ -72,8 +73,41 @@ class MDGeometryTest : public CxxTest::TestSuite
{
MDGeometry g;
TS_ASSERT(!g.hasOriginalWorkspace());
boost::shared_ptr<WorkspaceTester> ws(new WorkspaceTester());
g.setOriginalWorkspace(ws);
TS_ASSERT(g.hasOriginalWorkspace());
}

/** If a MDGeometry workspace holds a pointer to an original workspace
* that gets deleted, remove the pointer and allow it to be destructed.
*/
void test_OriginalWorkspace_gets_deleted()
{
MDGeometry g;
{
boost::shared_ptr<WorkspaceTester> ws(new WorkspaceTester());
AnalysisDataService::Instance().addOrReplace("MDGeometryTest_originalWS", ws);
g.setOriginalWorkspace(ws);
TS_ASSERT(g.hasOriginalWorkspace());
}
// Workspace is still valid even if it went out of scope
TS_ASSERT(g.getOriginalWorkspace())

// Create a different workspace and delete that
boost::shared_ptr<WorkspaceTester> ws2(new WorkspaceTester());
AnalysisDataService::Instance().addOrReplace("MDGeometryTest_some_other_ws", ws2);
AnalysisDataService::Instance().remove("MDGeometryTest_some_other_ws");
TSM_ASSERT("Different workspace does not get deleted incorrectly", g.hasOriginalWorkspace())

// Delete the right workspace (e.g. DeleteWorkspace algo)
AnalysisDataService::Instance().remove("MDGeometryTest_originalWS");
TSM_ASSERT("Original workspace reference was deleted.", !g.hasOriginalWorkspace());
TSM_ASSERT("Original workspace reference is cleared.", !g.getOriginalWorkspace());


}


};


Expand Down
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/MDEvents/src/SlicingAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ namespace MDEvents
m_axisAligned = getProperty("AxisAligned");

// Refer to the original workspace. Make sure that is possible
m_originalWS = m_inWS->getOriginalWorkspace();
m_originalWS = boost::dynamic_pointer_cast<IMDWorkspace>(m_inWS->getOriginalWorkspace());
if (m_originalWS)
{
if (m_axisAligned)
Expand Down
4 changes: 2 additions & 2 deletions Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ void SliceViewer::setWorkspace(Mantid::API::IMDWorkspace_sptr ws)

// For showing the original coordinates
ui.frmMouseInfo->setVisible(false);
IMDWorkspace_sptr origWS = m_ws->getOriginalWorkspace();
IMDWorkspace_sptr origWS = boost::dynamic_pointer_cast<IMDWorkspace>(m_ws->getOriginalWorkspace());
if (origWS)
{
CoordTransform * toOrig = m_ws->getTransformToOriginal();
Expand Down Expand Up @@ -919,7 +919,7 @@ void SliceViewer::showInfoAt(double x, double y)
ui.lblInfoSignal->setText(QString::number(signal, 'g', 4));

// Now show the coords in the original workspace
IMDWorkspace_sptr origWS = m_ws->getOriginalWorkspace();
IMDWorkspace_sptr origWS = boost::dynamic_pointer_cast<IMDWorkspace>(m_ws->getOriginalWorkspace());
if (origWS)
{
CoordTransform * toOrig = m_ws->getTransformToOriginal();
Expand Down

0 comments on commit 57fd372

Please sign in to comment.