Files
ThirdParty-6/ParaView-5.0.1/VTK/Geovis/Core/vtkGeoSource.cxx

251 lines
6.3 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSource.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*-------------------------------------------------------------------------
Copyright 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkGeoSource.h"
#include "vtkCollection.h"
#include "vtkConditionVariable.h"
#include "vtkDataObject.h"
#include "vtkGeoImageNode.h"
#include "vtkGeoTerrainNode.h"
#include "vtkMultiThreader.h"
#include "vtkMutexLock.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkTimerLog.h"
#include <map>
#include <utility>
#include <vector>
static VTK_THREAD_RETURN_TYPE vtkGeoSourceThreadStart(void* arg)
{
vtkGeoSource* self;
self = static_cast<vtkGeoSource *>(static_cast<vtkMultiThreader::ThreadInfo *>(arg)->UserData);
self->WorkerThread();
return VTK_THREAD_RETURN_VALUE;
}
class vtkGeoSource::implementation {
public:
std::map<std::pair<unsigned long, int>, vtkSmartPointer<vtkCollection> > OutputMap;
std::vector<int> ThreadIds;
};
vtkGeoSource::vtkGeoSource()
{
this->InputSet = vtkCollection::New();
this->InputSetLock = vtkMutexLock::New();
this->ProcessingSet = vtkCollection::New();
this->ProcessingSetLock = vtkMutexLock::New();
this->OutputSetLock = vtkMutexLock::New();
this->Lock = vtkMutexLock::New();
this->Condition = vtkConditionVariable::New();
this->StopThread = false;
this->Initialized = false;
this->Implementation = new implementation();
this->Threader = vtkMultiThreader::New();
}
vtkGeoSource::~vtkGeoSource()
{
this->ShutDown();
this->InputSet->Delete();
this->ProcessingSet->Delete();
this->Threader->Delete();
delete this->Implementation;
this->InputSetLock->Delete();
this->ProcessingSetLock->Delete();
this->OutputSetLock->Delete();
this->Condition->Delete();
this->Lock->Delete();
}
void vtkGeoSource::Initialize(int numThreads)
{
if(this->Initialized)
{
return;
}
int maxThreads = this->Threader->GetGlobalDefaultNumberOfThreads();
maxThreads = numThreads < maxThreads ? numThreads : maxThreads;
for(int i = 0; i < maxThreads; ++i)
{
this->Implementation->ThreadIds.push_back(
this->Threader->SpawnThread(vtkGeoSourceThreadStart, this));
}
this->Initialized = true;
}
void vtkGeoSource::ShutDown()
{
if (this->Implementation->ThreadIds.size() > 0)
{
this->Lock->Lock();
this->StopThread = true;
this->Condition->Broadcast();
this->Lock->Unlock();
std::vector<int>::iterator iter;
for(iter = this->Implementation->ThreadIds.begin();
iter != this->Implementation->ThreadIds.end();
++iter)
{
this->Threader->TerminateThread(*iter);
}
this->Implementation->ThreadIds.clear();
this->Implementation->OutputMap.clear();
}
this->Initialized = false;
}
vtkCollection* vtkGeoSource::GetRequestedNodes(vtkGeoTreeNode* node)
{
vtkCollection* c = 0;
this->OutputSetLock->Lock();
std::pair<unsigned long, int> p(node->GetId(), node->GetLevel());
if (this->Implementation->OutputMap.count(p) > 0)
{
c = this->Implementation->OutputMap[p];
if (c)
{
c->Register(0);
this->Implementation->OutputMap[p] = 0;
}
}
this->OutputSetLock->Unlock();
return c;
}
void vtkGeoSource::RequestChildren(vtkGeoTreeNode* node)
{
if(!this->Initialized)
{
vtkErrorMacro("Call Initialize() first in order to spawn worker threads.");
return;
}
this->InputSetLock->Lock();
this->InputSet->AddItem(node);
// Reference Count is 2 at this point. Decrease so that
// we can delete this copy of the node from the worker
// thread.
node->UnRegister(this);
this->Condition->Broadcast();
this->InputSetLock->Unlock();
}
void vtkGeoSource::WorkerThread()
{
bool isTerrainNode = false;
while (true)
{
this->Lock->Lock();
if (this->StopThread)
{
this->Lock->Unlock();
return;
}
this->Lock->Unlock();
this->InputSetLock->Lock();
// Try to find something to work on.
if (this->InputSet->GetNumberOfItems() > 0)
{
// Move from input set to processing set
vtkGeoTreeNode* node = vtkGeoTreeNode::SafeDownCast(this->InputSet->GetItemAsObject(0));
node->Register(this);
this->InputSet->RemoveItem(0);
this->InputSetLock->Unlock();
// Create appropriate child instances
vtkGeoTreeNode* child[4];
isTerrainNode = vtkGeoTerrainNode::SafeDownCast(node) != NULL ? true : false;
if (isTerrainNode)
{
for (int i = 0; i < 4; ++i)
{
child[i] = vtkGeoTerrainNode::New();
}
}
else
{
for (int i = 0; i < 4; ++i)
{
child[i] = vtkGeoImageNode::New();
}
}
// Fetch the children
bool success = true;
for (int i = 0; i < 4; ++i)
{
if (!this->FetchChild(node, i, child[i]))
{
success = false;
break;
}
}
// Move from processing set to output
this->OutputSetLock->Lock();
std::pair<unsigned long, int> p(node->GetId(), node->GetLevel());
this->Implementation->OutputMap[p] =
vtkSmartPointer<vtkCollection>::New();
if (success)
{
for (int i = 0; i < 4; ++i)
{
this->Implementation->OutputMap[p]->AddItem(child[i]);
}
}
this->OutputSetLock->Unlock();
node->Delete();
node = NULL;
for (int i = 0; i < 4; ++i)
{
child[i]->Delete();
}
}
else
{
this->InputSetLock->Unlock();
this->Lock->Lock();
// No Work, so lets wait till we're signaled again.
this->Condition->Wait( this->Lock );
this->Lock->Unlock();
}
}
}