Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkNonBlockingAlgorithm.h"
00019 #include "mitkCallbackFromGUIThread.h"
00020 #include "mitkDataStorage.h"
00021 #include <itkCommand.h>
00022
00023 namespace mitk {
00024
00025 NonBlockingAlgorithm::NonBlockingAlgorithm()
00026 : m_ThreadID(-1),
00027 m_UpdateRequests(0),
00028 m_KillRequest(false)
00029 {
00030 m_ParameterListMutex = itk::FastMutexLock::New();
00031 m_Parameters = PropertyList::New();
00032 m_MultiThreader = itk::MultiThreader::New();
00033 }
00034
00035 NonBlockingAlgorithm::~NonBlockingAlgorithm()
00036 {
00037 }
00038
00039 void mitk::NonBlockingAlgorithm::SetDataStorage(DataStorage& storage)
00040 {
00041 m_DataStorage = &storage;
00042 }
00043
00044 DataStorage* mitk::NonBlockingAlgorithm::GetDataStorage()
00045 {
00046 return m_DataStorage;
00047 }
00048
00049
00050 void NonBlockingAlgorithm::Initialize(const NonBlockingAlgorithm* itkNotUsed(other))
00051 {
00052
00053
00054
00055 BaseData::Pointer input;
00056 SetPointerParameter("Input", input );
00057
00058
00059 BaseData::Pointer output;
00060 SetPointerParameter("Output", output );
00061 }
00062
00063 void NonBlockingAlgorithm::SetPointerParameter(const char* parameter, BaseData* value)
00064 {
00065 m_ParameterListMutex->Lock();
00066 m_Parameters->SetProperty(parameter, SmartPointerProperty::New(value) );
00067 m_ParameterListMutex->Unlock();
00068 }
00069
00070 void NonBlockingAlgorithm::DefineTriggerParameter(const char* parameter)
00071 {
00072 BaseProperty* value = m_Parameters->GetProperty( parameter );
00073 if ( value
00074 && m_TriggerPropertyConnections.find(parameter) == m_TriggerPropertyConnections.end() )
00075 {
00076 itk::ReceptorMemberCommand<NonBlockingAlgorithm>::Pointer command = itk::ReceptorMemberCommand<NonBlockingAlgorithm>::New();
00077 command->SetCallbackFunction( this, &NonBlockingAlgorithm::TriggerParameterModified);
00078
00079 m_TriggerPropertyConnections[ parameter ] = value->AddObserver( itk::ModifiedEvent(), command );
00080 }
00081 }
00082
00083 void NonBlockingAlgorithm::UnDefineTriggerParameter(const char* parameter)
00084 {
00085 MapTypeStringUInt::iterator iter = m_TriggerPropertyConnections.find( parameter );
00086
00087 if ( iter != m_TriggerPropertyConnections.end() )
00088 {
00089 BaseProperty* value = m_Parameters->GetProperty( parameter );
00090
00091 MITK_ERROR(!value) << "NonBlockingAlgorithm::UnDefineTriggerProperty() in bad state." << std::endl; ;
00092
00093 value->RemoveObserver( m_TriggerPropertyConnections[parameter] );
00094 m_TriggerPropertyConnections.erase(iter);
00095 }
00096 }
00097
00098
00099 void NonBlockingAlgorithm::Reset()
00100 {
00101 Initialize();
00102 }
00103
00104
00105 void NonBlockingAlgorithm::StartBlockingAlgorithm()
00106 {
00107 StartAlgorithm();
00108 StopAlgorithm();
00109 }
00110
00111 void NonBlockingAlgorithm::StartAlgorithm()
00112 {
00113 if ( !ReadyToRun() ) return;
00114 if (m_KillRequest) return;
00115
00116 m_ParameterListMutex->Lock();
00117 m_ThreadParameters.m_Algorithm = this;
00118 ++m_UpdateRequests;
00119 m_ParameterListMutex->Unlock();
00120 if (m_ThreadID != -1)
00121 {
00122 return;
00123 }
00124
00125
00126 itk::ThreadFunctionType fpointer = &StaticNonBlockingAlgorithmThread;
00127 m_ThreadID = m_MultiThreader->SpawnThread( fpointer, &m_ThreadParameters);
00128 }
00129
00130 void NonBlockingAlgorithm::StopAlgorithm()
00131 {
00132 if (m_ThreadID == -1) return;
00133
00134 m_MultiThreader->TerminateThread( m_ThreadID );
00135 }
00136
00137
00138
00139 ITK_THREAD_RETURN_TYPE NonBlockingAlgorithm::StaticNonBlockingAlgorithmThread(void* param)
00140 {
00141
00142 itk::MultiThreader::ThreadInfoStruct* itkmttis = static_cast<itk::MultiThreader::ThreadInfoStruct*>(param);
00143
00144
00145 ThreadParameters* flsp = static_cast<ThreadParameters*>(itkmttis->UserData);
00146
00147 NonBlockingAlgorithm::Pointer algorithm = flsp->m_Algorithm;
00148
00149 if (!algorithm)
00150 {
00151 return ITK_THREAD_RETURN_VALUE;
00152 }
00153
00154 algorithm->m_ParameterListMutex->Lock();
00155 while ( algorithm->m_UpdateRequests > 0 )
00156 {
00157 algorithm->m_UpdateRequests = 0;
00158 algorithm->m_ParameterListMutex->Unlock();
00159
00160
00161 if ( algorithm->ThreadedUpdateFunction() )
00162 {
00163 itk::ReceptorMemberCommand<NonBlockingAlgorithm>::Pointer command = itk::ReceptorMemberCommand<NonBlockingAlgorithm>::New();
00164 command->SetCallbackFunction(algorithm, &NonBlockingAlgorithm::ThreadedUpdateSuccessful);
00165 CallbackFromGUIThread::GetInstance()->CallThisFromGUIThread(command);
00166
00167 }
00168 else
00169 {
00170 itk::ReceptorMemberCommand<NonBlockingAlgorithm>::Pointer command = itk::ReceptorMemberCommand<NonBlockingAlgorithm>::New();
00171 command->SetCallbackFunction(algorithm, &NonBlockingAlgorithm::ThreadedUpdateFailed);
00172 CallbackFromGUIThread::GetInstance()->CallThisFromGUIThread(command);
00173
00174 }
00175
00176 algorithm->m_ParameterListMutex->Lock();
00177 }
00178 algorithm->m_ParameterListMutex->Unlock();
00179
00180 return ITK_THREAD_RETURN_VALUE;
00181 }
00182
00183
00184 void NonBlockingAlgorithm::TriggerParameterModified(const itk::EventObject&)
00185 {
00186 StartAlgorithm();
00187 }
00188
00189 bool NonBlockingAlgorithm::ReadyToRun()
00190 {
00191 return true;
00192 }
00193
00194 bool NonBlockingAlgorithm::ThreadedUpdateFunction()
00195 {
00196 return true;
00197 }
00198
00199
00200 void NonBlockingAlgorithm::ThreadedUpdateSuccessful(const itk::EventObject&)
00201 {
00202 ThreadedUpdateSuccessful();
00203
00204 m_ParameterListMutex->Lock();
00205 m_ThreadID = -1;
00206 m_ParameterListMutex->Unlock();
00207 m_ThreadParameters.m_Algorithm = NULL;
00208 }
00209
00210 void NonBlockingAlgorithm::ThreadedUpdateSuccessful()
00211 {
00212
00213 InvokeEvent( ResultAvailable(this) );
00214 }
00215
00216
00217 void NonBlockingAlgorithm::ThreadedUpdateFailed(const itk::EventObject&)
00218 {
00219 ThreadedUpdateFailed();
00220
00221 m_ParameterListMutex->Lock();
00222 m_ThreadID = -1;
00223 m_ParameterListMutex->Unlock();
00224 m_ThreadParameters.m_Algorithm = NULL;
00225 }
00226
00227 void NonBlockingAlgorithm::ThreadedUpdateFailed()
00228 {
00229
00230 InvokeEvent( ProcessingError(this) );
00231 }
00232
00233 }
00234