Isis 3 Programmer Reference
Isis::CubeDataThread Class Reference

Encapsulation of Cube I/O with Change Notifications. More...

#include <CubeDataThread.h>

Inheritance diagram for Isis::CubeDataThread:
Inheritance graph
Collaboration diagram for Isis::CubeDataThread:
Collaboration graph

Public Slots

void ReadCube (int cubeId, int startSample, int startLine, int endSample, int endLine, int band, void *caller)
 This slot should be connected to and upon receiving a signal it will begin the necessary cube I/O to get this data.
 
void ReadWriteCube (int cubeId, int startSample, int startLine, int endSample, int endLine, int band, void *caller)
 This slot should be connected to and upon receiving a signal it will begin the necessary cube I/O to get this data.
 
void DoneWithData (int, const Isis::Brick *)
 When done processing with a brick (reading or writing) this slot needs to be signalled to free locks and memory.
 

Signals

void ReadReady (void *requester, int cubeId, const Isis::Brick *data)
 This signal will be emitted when ReadCube has finished processing.
 
void ReadWriteReady (void *requester, int cubeId, Isis::Brick *data)
 This signal will be emitted when ReadWriteCube has finished processing.
 
void BrickChanged (int cubeId, const Isis::Brick *data)
 DO NOT CONNECT TO THIS SIGNAL WITHOUT CALLING AddChangeListener().
 

Public Member Functions

 CubeDataThread ()
 This constructs a CubeDataThread().
 
virtual ~CubeDataThread ()
 This class is a self-contained thread, so normally it would be bad to simply delete it.
 
int AddCube (const FileName &fileName, bool mustOpenReadWrite=false)
 This method is designed to be callable from any thread before data is requested, though no known side effects exist if this is called during other I/O operations (though I don't recommend it).
 
int AddCube (Cube *cube)
 This method is designed to be callable from any thread before data is requested, though no known side effects exist if this is called during other I/O operations (though I don't recommend it).
 
void RemoveCube (int cubeId)
 Removes a cube from this lock manager.
 
void AddChangeListener ()
 You must call this method after connecting to the BrickChanged signal, otherwise you are not guaranteed a good Brick pointer.
 
void RemoveChangeListener ()
 You must call this method after disconnecting from the BrickChanged signal, otherwise bricks cannot be freed from memory.
 
int BricksInMemory ()
 This is a helper method for both testing/debugging and general information that provides the current number of bricks in memory.
 
UniversalGroundMapGetUniversalGroundMap (int cubeId) const
 This returns a new Universal Ground Map given a Cube ID.
 
const CubeGetCube (int cubeId) const
 This returns a constant pointer to a Cube at the given Cube ID.
 
int FindCubeId (const Cube *) const
 Given a Cube pointer, return the cube ID associated with it.
 

Private Member Functions

 CubeDataThread (const CubeDataThread &cdt)
 Assigning CubeDataThreads to eachother is bad, so this has been intentionally not implemented!
 
const CubeDataThreadoperator= (CubeDataThread rhs)
 Assigning CubeDataThreads to eachother is bad, so this has been intentionally not implemented!
 
int OverlapIndex (const Brick *initial, int cubeId, int instanceNum, bool &exact)
 This is a searching method used to identify overlapping data already in memory.
 
void GetCubeData (int cubeId, int ss, int sl, int es, int el, int band, void *caller, bool sharedLock)
 This helper method reads in cube data and handles the locking of similar bricks appropriately.
 
void AcquireLock (QReadWriteLock *lockObject, bool readLock)
 This method is exclusively used to acquire locks.
 
bool FreeBrick (int brickIndex)
 This is used internally to delete bricks when possible.
 

Private Attributes

QMap< int, QPair< bool, Cube * > > * p_managedCubes
 This is a list of the opened cubes.
 
QMutex * p_threadSafeMutex
 This locks the member variable p_managedCubes and p_managedData itself.
 
QList< QPair< QReadWriteLock *, Brick * > > * p_managedData
 This is a list of bricks in memory and their locks.
 
QList< int > * p_managedDataSources
 This is the associated cube ID with each brick.
 
int p_numChangeListeners
 This is the number of shaded locks to put on a brick when changes made.
 
unsigned int p_currentId
 This is the unique id counter for cubes.
 
bool p_stopping
 This is set to help the shutdown process when deleted.
 
unsigned int p_currentLocksWaiting
 Number of locks being attempted that re-entered the event loop.
 

Detailed Description

Encapsulation of Cube I/O with Change Notifications.

The main purpose of this class is to create cube change notifications, ideal for GUI's with changing cubes. This class is designed to encapsulate Cube I/O into a separate thread and serializes each cube I/O. This class also speeds up I/O by reusing bricks instead of always reading from the disk.

This is not a full concurrency control/transaction handler. Consistent states are not guaranteed, though a consistent state for any given brick is, and results from reads do not guaranteed serial equivalence. Deadlocks are possible, if two processes want to R/W to the same sections of data, and it is up to the users of this class to avoid such conditions.

Author
2010-01-15 Steven Lambright
History

2010-04-12 Eric Hyer - Added check for valid cube ID's for slots ReadCube and ReadWriteCube.

2010-07-29 Eric Hyer - AcquireLock now flushes events for this thread instead of the main eventloop's thread.

2010-08-12 Steven Lambright - Fixed memory leak and simplified acquiring write bricks

2010-08-23 Eric Hyer - Added the FindCubeId method

2010-08-24 Eric Hyer - Added the RemoveCube method

2012-02-27 Jai Rideout and Steven Lambright - Made BricksInMemory() thread-safe. Fixes #733.

2016-06-21 Kris Becker - Properly forward declare QPair as struct not class

Todo
Add state recording/reverting functionality

Definition at line 59 of file CubeDataThread.h.

Constructor & Destructor Documentation

◆ CubeDataThread() [1/2]

Isis::CubeDataThread::CubeDataThread ( )

This constructs a CubeDataThread().

This will spawn a new thread and move the ownership of this instance to itself (so slots are called in this self-contained thread).

Definition at line 34 of file CubeDataThread.cpp.

References p_currentId, p_currentLocksWaiting, p_managedCubes, p_managedData, p_managedDataSources, p_numChangeListeners, p_stopping, and p_threadSafeMutex.

◆ ~CubeDataThread()

Isis::CubeDataThread::~CubeDataThread ( )
virtual

This class is a self-contained thread, so normally it would be bad to simply delete it.

However, this destructor will synchronize the shutdown of the thread so you can safely delete an instance of this class without using the deleteLater() method.

Definition at line 65 of file CubeDataThread.cpp.

References p_managedCubes, p_managedData, p_managedDataSources, p_stopping, and p_threadSafeMutex.

◆ CubeDataThread() [2/2]

Isis::CubeDataThread::CubeDataThread ( const CubeDataThread & cdt)
private

Assigning CubeDataThreads to eachother is bad, so this has been intentionally not implemented!

Parameters
cdtThe CubeDataThread that would be used to copy construct this CubeDataThread if this method were implemented (which its not)

Member Function Documentation

◆ AcquireLock()

void Isis::CubeDataThread::AcquireLock ( QReadWriteLock * lockObject,
bool readLock )
private

This method is exclusively used to acquire locks.

This handles the problem of being unable to receive signals that would free locks while waiting for a lock to be made.

Parameters
lockObjectLock object we're trying to acquire a lock on
readLockTrue if we're trying for read lock, false for read/write

Definition at line 370 of file CubeDataThread.cpp.

References p_currentLocksWaiting, and p_stopping.

Referenced by DoneWithData(), and GetCubeData().

◆ AddChangeListener()

void Isis::CubeDataThread::AddChangeListener ( )

You must call this method after connecting to the BrickChanged signal, otherwise you are not guaranteed a good Brick pointer.

Definition at line 229 of file CubeDataThread.cpp.

References p_numChangeListeners.

Referenced by Isis::CubeViewport::CubeViewport(), and Isis::CubeDataThreadTester::NotifyChangeTest().

◆ AddCube() [1/2]

int Isis::CubeDataThread::AddCube ( const FileName & fileName,
bool mustOpenReadWrite = false )

This method is designed to be callable from any thread before data is requested, though no known side effects exist if this is called during other I/O operations (though I don't recommend it).

If possible, the cube will be opened with R/W permissions, otherwise it will be opened with read-only access

Parameters
fileNameThe cube to open
mustOpenReadWriteIf true and cube has read-only access then an exception will be thrown
Returns
int The cube ID necessary for retrieving information about this cube in the future.

Definition at line 124 of file CubeDataThread.cpp.

References Isis::FileName::expanded(), p_currentId, p_managedCubes, and p_threadSafeMutex.

Referenced by Isis::CubeViewport::CubeViewport().

◆ AddCube() [2/2]

int Isis::CubeDataThread::AddCube ( Cube * cube)

This method is designed to be callable from any thread before data is requested, though no known side effects exist if this is called during other I/O operations (though I don't recommend it).

Ownership is not taken of this cube

Parameters
cubeThe cube to encapsulate
Returns
int The cube ID necessary for retrieving information about this cube in the future.

Definition at line 167 of file CubeDataThread.cpp.

References p_currentId, p_managedCubes, and p_threadSafeMutex.

◆ BrickChanged

void Isis::CubeDataThread::BrickChanged ( int cubeId,
const Isis::Brick * data )
signal

DO NOT CONNECT TO THIS SIGNAL WITHOUT CALLING AddChangeListener().

When a write occurs, and change listeners exist, this signal is emitted with the new data.

When done with the data, given you are the requester, you call the DoneWithData slot (via a signal).

Parameters
cubeIdCube ID of the change
dataArea written to the cube

Referenced by DoneWithData().

◆ BricksInMemory()

int Isis::CubeDataThread::BricksInMemory ( )

This is a helper method for both testing/debugging and general information that provides the current number of bricks in memory.

Returns
int Count of how many bricks reside in memory.

Definition at line 728 of file CubeDataThread.cpp.

References p_managedData, and p_threadSafeMutex.

◆ DoneWithData

void Isis::CubeDataThread::DoneWithData ( int cubeId,
const Isis::Brick * brickDone )
slot

When done processing with a brick (reading or writing) this slot needs to be signalled to free locks and memory.

Parameters
cubeIdCube associated with the brick
brickDoneBrick pointer given by ReadReady, ReadWriteReady or BrickChanged. An equivalent brick is also acceptable (exact same range, but not same pointer).

Definition at line 585 of file CubeDataThread.cpp.

References AcquireLock(), BrickChanged(), FreeBrick(), OverlapIndex(), p_managedCubes, p_managedData, p_managedDataSources, p_numChangeListeners, p_threadSafeMutex, and Isis::IException::Programmer.

◆ FindCubeId()

int Isis::CubeDataThread::FindCubeId ( const Cube * cubeToFind) const

Given a Cube pointer, return the cube ID associated with it.

Parameters
cubeToFindCube to look up the ID for
Returns
the cube ID associated the given Cube pointer

Definition at line 350 of file CubeDataThread.cpp.

References p_managedCubes, and Isis::IException::Programmer.

Referenced by Isis::CubeViewport::CubeViewport().

◆ FreeBrick()

bool Isis::CubeDataThread::FreeBrick ( int brickIndex)
private

This is used internally to delete bricks when possible.

Parameters
brickIndexBrick to request deletion
Returns
bool True if deletion actually happened

Definition at line 679 of file CubeDataThread.cpp.

References p_currentLocksWaiting, p_managedData, p_managedDataSources, p_threadSafeMutex, and Isis::IException::Programmer.

Referenced by DoneWithData(), and GetCubeData().

◆ GetCube()

const Cube * Isis::CubeDataThread::GetCube ( int cubeId) const

This returns a constant pointer to a Cube at the given Cube ID.

Parameters
cubeIdThe Cube ID of the Cube that needs its pointer returned
Returns
A thread-safe pointer to the requested Cube.

Definition at line 761 of file CubeDataThread.cpp.

References p_managedCubes, and Isis::IException::Programmer.

◆ GetCubeData()

void Isis::CubeDataThread::GetCubeData ( int cubeId,
int ss,
int sl,
int es,
int el,
int band,
void * caller,
bool sharedLock )
private

This helper method reads in cube data and handles the locking of similar bricks appropriately.

Parameters
cubeIdCube ID To Read From
ssStarting Sample Position
slStarting Line Position
esEnding Sample Position
elEnding Line Position
bandBand Number To Read From (multi-band bricks not supported at this time)
callerA pointer to the calling class, used to identify who requested the data when they receive either the ReadReady or the ReadWriteReady signal
sharedLockTrue if read-only, false if read-write

Definition at line 257 of file CubeDataThread.cpp.

References AcquireLock(), FreeBrick(), OverlapIndex(), p_managedCubes, p_managedData, p_managedDataSources, p_stopping, p_threadSafeMutex, ReadReady(), and ReadWriteReady().

Referenced by ReadCube(), and ReadWriteCube().

◆ GetUniversalGroundMap()

UniversalGroundMap * Isis::CubeDataThread::GetUniversalGroundMap ( int cubeId) const

This returns a new Universal Ground Map given a Cube ID.

Ownership is given to the caller.

Parameters
cubeIdThe Cube ID of the Cube that needs its ground map returned.
Returns
UniversalGroundMap * Ground Map associated with the cube.

Definition at line 744 of file CubeDataThread.cpp.

References p_managedCubes, and Isis::IException::Programmer.

◆ operator=()

const CubeDataThread & Isis::CubeDataThread::operator= ( CubeDataThread rhs)
private

Assigning CubeDataThreads to eachother is bad, so this has been intentionally not implemented!

Parameters
rhsThe right hand side CubeDataThread in the assignment operation.
Returns
would return this if it was implemented :)

◆ OverlapIndex()

int Isis::CubeDataThread::OverlapIndex ( const Brick * overlapping,
int cubeId,
int instanceNum,
bool & exact )
private

This is a searching method used to identify overlapping data already in memory.

Parameters
overlappingBrick to check for overlaps with
cubeIdCube ID asssociated with this brick
instanceNumWhich instance of overlap to return
exactThis is set to false if the match found is not exactly the overlapping brick.
Returns
int -1 for none found, otherwise the index into p_managedData and p_managedDataSources that an overlap was found at

Definition at line 488 of file CubeDataThread.cpp.

References p_managedData, and Isis::Buffer::Sample().

Referenced by DoneWithData(), and GetCubeData().

◆ ReadCube

void Isis::CubeDataThread::ReadCube ( int cubeId,
int startSample,
int startLine,
int endSample,
int endLine,
int band,
void * caller )
slot

This slot should be connected to and upon receiving a signal it will begin the necessary cube I/O to get this data.

When the data is available, a ReadReady signal will be emitted with the parameter caller being equal to the requester pointer in the signal. You should pass "this" for caller, and you must ignore all ReadReady signals which do not have "requester == this" -> otherwise your pointer is not guaranteed.

Parameters
cubeIdCube to read from
startSampleStarting Sample Position
startLineStarting Line Position
endSampleEnding Sample Position
endLineEnding Line Position
bandBand Number To Read From (multi-band bricks not supported at this time)
callerA pointer to the calling class, used to identify who requested the data when they receive the ReadReady signal

Definition at line 426 of file CubeDataThread.cpp.

References GetCubeData(), p_managedCubes, and Isis::IException::Programmer.

◆ ReadReady

void Isis::CubeDataThread::ReadReady ( void * requester,
int cubeId,
const Isis::Brick * data )
signal

This signal will be emitted when ReadCube has finished processing.

When done with the data, given you are the requester, you call the DoneWithData slot (via a signal).

Parameters
requesterPointer to the calling class (must ignore all ReadReady signals where this != requester)
cubeIdCube ID of the cube the data is from
dataThe data in the cube

Referenced by GetCubeData().

◆ ReadWriteCube

void Isis::CubeDataThread::ReadWriteCube ( int cubeId,
int startSample,
int startLine,
int endSample,
int endLine,
int band,
void * caller )
slot

This slot should be connected to and upon receiving a signal it will begin the necessary cube I/O to get this data.

When the data is available, a ReadWriteReady signal will be emitted with the parameter caller being equal to the requester pointer in the signal. You should pass "this" for caller, and you must ignore all ReadReady signals which do not have "requester == this" -> otherwise your pointer is not guaranteed and you are corrupting the process of the real requester.

Parameters
cubeIdCube to read from
startSampleStarting Sample Position
startLineStarting Line Position
endSampleEnding Sample Position
endLineEnding Line Position
bandBand Number To Read From (multi-band bricks not supported at this time)
callerA pointer to the calling class, used to identify who requested the data when they receive the ReadWriteReady signal

Definition at line 461 of file CubeDataThread.cpp.

References GetCubeData(), p_managedCubes, and Isis::IException::Programmer.

◆ ReadWriteReady

void Isis::CubeDataThread::ReadWriteReady ( void * requester,
int cubeId,
Isis::Brick * data )
signal

This signal will be emitted when ReadWriteCube has finished processing.

When done with the data, given you are the requester, you call the DoneWithData slot (via a signal).

Parameters
requesterPointer to the calling class (must ignore all ReadReady signals where this != requester)
cubeIdCube ID of the cube the data is from
dataThe data in the cube, also where you should write changes

Referenced by GetCubeData().

◆ RemoveChangeListener()

void Isis::CubeDataThread::RemoveChangeListener ( )

You must call this method after disconnecting from the BrickChanged signal, otherwise bricks cannot be freed from memory.

Definition at line 237 of file CubeDataThread.cpp.

References p_numChangeListeners.

Referenced by Isis::CubeViewport::~CubeViewport().

◆ RemoveCube()

void Isis::CubeDataThread::RemoveCube ( int cubeId)

Removes a cube from this lock manager.

Parameters
cubeIdThe cube to be deleted's ID

Definition at line 191 of file CubeDataThread.cpp.

References p_managedCubes, p_managedDataSources, p_threadSafeMutex, and Isis::IException::Programmer.

Member Data Documentation

◆ p_currentId

unsigned int Isis::CubeDataThread::p_currentId
private

This is the unique id counter for cubes.

Definition at line 208 of file CubeDataThread.h.

Referenced by AddCube(), AddCube(), and CubeDataThread().

◆ p_currentLocksWaiting

unsigned int Isis::CubeDataThread::p_currentLocksWaiting
private

Number of locks being attempted that re-entered the event loop.

As long as this isn't zero, no bricks should be removed from p_managedData.

Definition at line 217 of file CubeDataThread.h.

Referenced by AcquireLock(), CubeDataThread(), and FreeBrick().

◆ p_managedCubes

QMap< int, QPair< bool, Cube * > >* Isis::CubeDataThread::p_managedCubes
private

This is a list of the opened cubes.

Since opening cubes is allowed in other threads (via AddCube(...)) and is accessed with many threads, all operations on this map must be serialized (non-simultaneous). The p_managedCubesMutex enables this. The bool indicates ownership.

Definition at line 171 of file CubeDataThread.h.

Referenced by AddCube(), AddCube(), CubeDataThread(), DoneWithData(), FindCubeId(), GetCube(), GetCubeData(), GetUniversalGroundMap(), ReadCube(), ReadWriteCube(), RemoveCube(), and ~CubeDataThread().

◆ p_managedData

QList< QPair<QReadWriteLock *, Brick *> >* Isis::CubeDataThread::p_managedData
private

This is a list of bricks in memory and their locks.

The following assumptions are vital or at least important for understanding this data structure: 1) No two bricks have the exact same area. 2) Deletions may only happen in the destructor or in FreeBrick(int) 3) A brick with no locks on it is available for deletion later, but may not be deleted if p_currentLocksWaiting != 0 (something is attempting a lock somewhere else). 4) Bricks may overlap, but locks only pertain to exact matches. 5) If you want to make an exclusive (R/W) lock on a brick, you must first make all overlapping bricks available for deletion (and/or delete) 6) If you wish to make a shared (R) lock on a brick, no overlapping bricks can be write locked. 7) All operations happen in this thread in order to prevent checks happening for access executing simultaneously, at least more than AcquireLock() allows. 8) New bricks must be appended to the end of this list. 8) Searches for conflicts must start at the beginning of this list and proceed to the end. 10) No NULL or invalid pointers may exist in this list.

Definition at line 199 of file CubeDataThread.h.

Referenced by BricksInMemory(), CubeDataThread(), DoneWithData(), FreeBrick(), GetCubeData(), OverlapIndex(), and ~CubeDataThread().

◆ p_managedDataSources

QList< int >* Isis::CubeDataThread::p_managedDataSources
private

This is the associated cube ID with each brick.

Definition at line 202 of file CubeDataThread.h.

Referenced by CubeDataThread(), DoneWithData(), FreeBrick(), GetCubeData(), RemoveCube(), and ~CubeDataThread().

◆ p_numChangeListeners

int Isis::CubeDataThread::p_numChangeListeners
private

This is the number of shaded locks to put on a brick when changes made.

Definition at line 205 of file CubeDataThread.h.

Referenced by AddChangeListener(), CubeDataThread(), DoneWithData(), and RemoveChangeListener().

◆ p_stopping

bool Isis::CubeDataThread::p_stopping
private

This is set to help the shutdown process when deleted.

Definition at line 211 of file CubeDataThread.h.

Referenced by AcquireLock(), CubeDataThread(), GetCubeData(), and ~CubeDataThread().

◆ p_threadSafeMutex

QMutex* Isis::CubeDataThread::p_threadSafeMutex
private

This locks the member variable p_managedCubes and p_managedData itself.

Definition at line 174 of file CubeDataThread.h.

Referenced by AddCube(), AddCube(), BricksInMemory(), CubeDataThread(), DoneWithData(), FreeBrick(), GetCubeData(), RemoveCube(), and ~CubeDataThread().


The documentation for this class was generated from the following files: