USGS

Isis 3.0 Object Programmers' Reference

Home

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.
History:
2010-07-29 Eric Hyer - AcquireLock now flushes events for this thread instead of the main eventloop's thread.
History:
2010-08-12 Steven Lambright - Fixed memory leak and simplified acquiring write bricks
History:
2010-08-23 Eric Hyer - Added the FindCubeId method
History:
2010-08-24 Eric Hyer - Added the RemoveCube method
History:
2012-02-27 Jai Rideout and Steven Lambright - Made BricksInMemory() thread-safe. Fixes #733.
Todo:
Add state recording/reverting functionality

Definition at line 52 of file CubeDataThread.h.

Constructor & Destructor Documentation

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 29 of file CubeDataThread.cpp.

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

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 60 of file CubeDataThread.cpp.

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

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

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 365 of file CubeDataThread.cpp.

References p_currentLocksWaiting, and p_stopping.

Referenced by DoneWithData(), and GetCubeData().

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 224 of file CubeDataThread.cpp.

References p_numChangeListeners.

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

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 119 of file CubeDataThread.cpp.

References Isis::Cube::open(), p_currentId, p_managedCubes, and p_threadSafeMutex.

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

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 162 of file CubeDataThread.cpp.

References p_currentId, p_managedCubes, and p_threadSafeMutex.

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().

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.

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 581 of file CubeDataThread.cpp.

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

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 345 of file CubeDataThread.cpp.

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

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

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 678 of file CubeDataThread.cpp.

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

Referenced by DoneWithData(), and GetCubeData().

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 _FILEINFO_, p_managedCubes, and Isis::IException::Programmer.

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 252 of file CubeDataThread.cpp.

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

Referenced by ReadCube(), and ReadWriteCube().

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 _FILEINFO_, p_managedCubes, and Isis::IException::Programmer.

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 :)
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 483 of file CubeDataThread.cpp.

References Isis::Buffer::Band(), Isis::Buffer::Line(), p_managedData, p_managedDataSources, Isis::Buffer::Sample(), and Isis::Buffer::size().

Referenced by DoneWithData(), and GetCubeData().

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 421 of file CubeDataThread.cpp.

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

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().

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 456 of file CubeDataThread.cpp.

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

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().

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 232 of file CubeDataThread.cpp.

References p_numChangeListeners.

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

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

Removes a cube from this lock manager.

Parameters
cubeIdThe cube to be deleted's ID

Definition at line 186 of file CubeDataThread.cpp.

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

Member Data Documentation

unsigned int Isis::CubeDataThread::p_currentId
private

This is the unique id counter for cubes.

Definition at line 201 of file CubeDataThread.h.

Referenced by AddCube(), and CubeDataThread().

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 210 of file CubeDataThread.h.

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

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 164 of file CubeDataThread.h.

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

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 192 of file CubeDataThread.h.

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

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

This is the associated cube ID with each brick.

Definition at line 195 of file CubeDataThread.h.

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

int Isis::CubeDataThread::p_numChangeListeners
private

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

Definition at line 198 of file CubeDataThread.h.

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

bool Isis::CubeDataThread::p_stopping
private

This is set to help the shutdown process when deleted.

Definition at line 204 of file CubeDataThread.h.

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

QMutex* Isis::CubeDataThread::p_threadSafeMutex
private

This locks the member variable p_managedCubes and p_managedData itself.

Definition at line 167 of file CubeDataThread.h.

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


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