From b46ca65e61fa01b0d7032cb350f74d86830c124e Mon Sep 17 00:00:00 2001 From: richterm Date: Tue, 13 Nov 2007 08:17:56 +0000 Subject: [PATCH] implement block forwarding --- HLT/BASE/AliHLTConsumerDescriptor.cxx | 25 ++++---- HLT/BASE/AliHLTConsumerDescriptor.h | 13 ++-- HLT/BASE/AliHLTDataBuffer.cxx | 86 ++++++++++++++++++++++----- HLT/BASE/AliHLTDataBuffer.h | 70 +++++++++++++++++++--- HLT/BASE/AliHLTTask.cxx | 42 ++++++++----- HLT/BASE/AliHLTTask.h | 4 ++ 6 files changed, 184 insertions(+), 56 deletions(-) diff --git a/HLT/BASE/AliHLTConsumerDescriptor.cxx b/HLT/BASE/AliHLTConsumerDescriptor.cxx index 1d07bed1e68..0ae25ea319a 100644 --- a/HLT/BASE/AliHLTConsumerDescriptor.cxx +++ b/HLT/BASE/AliHLTConsumerDescriptor.cxx @@ -61,27 +61,26 @@ AliHLTConsumerDescriptor::~AliHLTConsumerDescriptor() } } -int AliHLTConsumerDescriptor::SetActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) +int AliHLTConsumerDescriptor::SetActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment) { // see header file for function documentation int iResult=0; - AliHLTDataBuffer::AliHLTDataSegment segment(offset, size); fSegments.push_back(segment); //HLTDebug("set active segment (%d:%d) for consumer %p", offset, size, this); return iResult; } -int AliHLTConsumerDescriptor::CheckActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) +int AliHLTConsumerDescriptor::CheckActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment) { // see header file for function documentation int iResult=0; if (fSegments.size()>0) { - vector::iterator segment=fSegments.begin(); - while (segment!=fSegments.end()) { - if ((iResult=((*segment).fSegmentOffset==offset && (*segment).fSegmentSize==size))>0) { + vector::iterator element=fSegments.begin(); + while (element!=fSegments.end()) { + if ((iResult=(segment==(*element)))>0) { break; } - segment++; + element++; } } else { //HLTWarning("no data segment active for consumer %p", this); @@ -90,18 +89,18 @@ int AliHLTConsumerDescriptor::CheckActiveDataSegment(AliHLTUInt32_t offset, AliH return iResult; } -int AliHLTConsumerDescriptor::ReleaseActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) +int AliHLTConsumerDescriptor::ReleaseActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment) { // see header file for function documentation int iResult=0; if (fSegments.size()>0) { - vector::iterator segment=fSegments.begin(); - while (segment!=fSegments.end()) { - if ((iResult=((*segment).fSegmentOffset==offset && (*segment).fSegmentSize==size))>0) { - fSegments.erase(segment); + vector::iterator element=fSegments.begin(); + while (element!=fSegments.end()) { + if ((iResult=(segment==(*element)))>0) { + fSegments.erase(element); break; } - segment++; + element++; } if (iResult==0) { //HLTWarning("no data segment (%d:%d) active for consumer %p", offset, size, this); diff --git a/HLT/BASE/AliHLTConsumerDescriptor.h b/HLT/BASE/AliHLTConsumerDescriptor.h index aa678350a3e..fe056120a67 100644 --- a/HLT/BASE/AliHLTConsumerDescriptor.h +++ b/HLT/BASE/AliHLTConsumerDescriptor.h @@ -48,20 +48,18 @@ class AliHLTConsumerDescriptor : public TObject, public AliHLTLogging { * Set an active data segment. * the pointer will be handled in a container, no allocation, copy or * cleanup. - * @param offset offset of the segment in the buffer - * @param size size of the segment in the buffer + * @param segment segment descriptor * @return >=0 if succeeded */ - int SetActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size); + int SetActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment); /** * Check whether there is an active data segment of certain size with * certain offset. - * @param offset offset of the data segment in the data buffer - * @param size size of the data segment in the data buffer + * @param segment segment descriptor * @return > if existend, 0 if not */ - int CheckActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size); + int CheckActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment); /** find an active data segment of certain size with certain offset * will see if this is necessary @@ -77,8 +75,9 @@ class AliHLTConsumerDescriptor : public TObject, public AliHLTLogging { int GetNofActiveSegments() {return fSegments.size();}; /** + * @param segment segment descriptor */ - int ReleaseActiveDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size); + int ReleaseActiveDataSegment(AliHLTDataBuffer::AliHLTDataSegment segment); private: /** copy constructor prohibited */ diff --git a/HLT/BASE/AliHLTDataBuffer.cxx b/HLT/BASE/AliHLTDataBuffer.cxx index 5751583f67f..4503d842a6a 100644 --- a/HLT/BASE/AliHLTDataBuffer.cxx +++ b/HLT/BASE/AliHLTDataBuffer.cxx @@ -35,6 +35,7 @@ using namespace std; #include "AliHLTDataBuffer.h" #include "AliHLTConsumerDescriptor.h" #include "AliHLTComponent.h" +#include "AliHLTTask.h" #include #include //#include @@ -53,7 +54,9 @@ AliHLTDataBuffer::AliHLTDataBuffer() fActiveConsumers(), fReleasedConsumers(), fpBuffer(NULL), - fFlags(0) + fFlags(0), + fForwardedSegmentSources(), + fForwardedSegments() { // see header file for class documentation // or @@ -138,6 +141,9 @@ int AliHLTDataBuffer::FindMatchingDataSegments(const AliHLTComponent* pConsumer, // all blocks are passed to the consumer, which is the policy also in // PubSub tgtList.assign(fSegments.begin(), fSegments.end()); + + // add all forwarded blocks + tgtList.insert(tgtList.begin(), fForwardedSegments.begin(), fForwardedSegments.end()); iResult=tgtList.size(); return iResult; @@ -169,7 +175,7 @@ int AliHLTDataBuffer::Subscribe(const AliHLTComponent* pConsumer, AliHLTComponen // see header file for function documentation int iResult=0; if (pConsumer && arrayBlockDesc) { - if (fpBuffer) { + if (1/*fpBuffer*/) { AliHLTConsumerDescriptor* pDesc=FindConsumer(pConsumer, fConsumers); if (pDesc) { AliHLTDataSegmentList tgtList; @@ -190,14 +196,13 @@ int AliHLTDataBuffer::Subscribe(const AliHLTComponent* pConsumer, AliHLTComponen // For incoming data blocks, fOffset must be ignored by the // processing component. It is set for bookkeeping in the framework. // fPtr always points to the beginning of the data. - arrayBlockDesc[i].fOffset=(*segment).fSegmentOffset; - AliHLTUInt8_t* pTgt=*fpBuffer; - pTgt+=(*segment).fSegmentOffset; + arrayBlockDesc[i].fOffset=0; + AliHLTUInt8_t* pTgt=*segment; arrayBlockDesc[i].fPtr=reinterpret_cast(pTgt); arrayBlockDesc[i].fSize=(*segment).fSegmentSize; arrayBlockDesc[i].fDataType=(*segment).fDataType; arrayBlockDesc[i].fSpecification=(*segment).fSpecification; - pDesc->SetActiveDataSegment(arrayBlockDesc[i].fOffset, arrayBlockDesc[i].fSize); + pDesc->SetActiveDataSegment(*segment); HLTDebug("component %p (%s) subscribed to segment #%d offset %d size %d data type %s %#x", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID(), i, arrayBlockDesc[i].fOffset, arrayBlockDesc[i].fSize, (AliHLTComponent::DataType2Text(arrayBlockDesc[i].fDataType)).c_str(), @@ -211,7 +216,10 @@ int AliHLTDataBuffer::Subscribe(const AliHLTComponent* pConsumer, AliHLTComponen iResult=-ENOSPC; } else { // move this consumer to the active list - if (ChangeConsumerState(pDesc, fConsumers, fActiveConsumers)>=0) { + if (i==0) { + ChangeConsumerState(pDesc, fConsumers, fReleasedConsumers); + HLTDebug("no input data for component %p (%s) available", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID()); + } else if (ChangeConsumerState(pDesc, fConsumers, fActiveConsumers)>=0) { HLTDebug("component %p (%s) subscribed to data buffer %p", pConsumer, ((AliHLTComponent*)pConsumer)->GetComponentID(), this); } else { // TODO: cleanup the consumer descriptor correctly @@ -242,23 +250,54 @@ int AliHLTDataBuffer::Subscribe(const AliHLTComponent* pConsumer, AliHLTComponen return iResult; } -int AliHLTDataBuffer::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTComponent* pConsumer) +int AliHLTDataBuffer::Release(AliHLTComponentBlockData* pBlockDesc, + const AliHLTComponent* pConsumer, + const AliHLTTask* pOwnerTask) { // see header file for function documentation int iResult=0; if (pBlockDesc && pConsumer) { AliHLTConsumerDescriptor* pDesc=FindConsumer(pConsumer, fActiveConsumers); if (pDesc) { - if ((iResult=pDesc->CheckActiveDataSegment(pBlockDesc->fOffset, pBlockDesc->fSize))!=1) { + if ((iResult=pDesc->CheckActiveDataSegment(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)))!=1) { HLTWarning("data segment missmatch, component %p has not subscribed to a segment with offset %#x and size %d", pConsumer, pBlockDesc->fOffset, pBlockDesc->fSize); // TODO: appropriate error handling, but so far optional iResult=0; } else { - pDesc->ReleaseActiveDataSegment(pBlockDesc->fOffset, pBlockDesc->fSize); - pBlockDesc->fOffset=0; - pBlockDesc->fPtr=NULL; - pBlockDesc->fSize=0; + pDesc->ReleaseActiveDataSegment(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)); + } + if (GetNofPendingConsumers()==0 && fForwardedSegments.size()>0) { + // last consumer, release forwarded segments + assert(fForwardedSegments.size()==fForwardedSegmentSources.size()); + AliHLTDataSegmentList::iterator segment=fForwardedSegments.begin(); + AliHLTTaskPList::iterator src=fForwardedSegmentSources.begin(); + //HLTDebug("%p checking forwarded segments", this); + for (; segment!=fForwardedSegments.end(); segment++, src++) { + //HLTDebug("segment ptr=%p offset=%d size=%d\n" + // "block ptr=%p offset=%d size=%d", (*segment).fPtr, (*segment).fSegmentOffset, (*segment).fSegmentSize, pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize); + if ((*segment)==AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)) { + //HLTDebug("release segment of task %p", *src); + assert((*src)!=NULL); + if ((*src)!=NULL) { + if ((*src)->Release(pBlockDesc, pOwnerTask)>=0) { + HLTDebug("task %s (%p) released forwarded segment %p size %d of task %s (%p)", + pOwnerTask->GetName(), pOwnerTask, (*segment).GetPtr(), (*segment).GetSize(), + (*src)->GetName(), *src); + } else { + HLTError("task %s (%p) failed releasing forwarded segment %p size %d of task %s (%p)", + pOwnerTask->GetName(), pOwnerTask, (*segment).GetPtr(), (*segment).GetSize(), + (*src)->GetName(), *src); + } + } + fForwardedSegments.erase(segment); + fForwardedSegmentSources.erase(src); + break; + } + } } + pBlockDesc->fOffset=0; + pBlockDesc->fPtr=NULL; + pBlockDesc->fSize=0; if (pDesc->GetNofActiveSegments()==0) { if ((iResult=ChangeConsumerState(pDesc, fActiveConsumers, fReleasedConsumers))>=0) { if (GetNofActiveConsumers()==0 && GetNofPendingConsumers()==0) { @@ -281,6 +320,17 @@ int AliHLTDataBuffer::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLT return iResult; } +int AliHLTDataBuffer::Forward(AliHLTTask* pSrcTask, AliHLTComponentBlockData* pBlockDesc) +{ + // see header file for function documentation + if (pSrcTask==NULL || pBlockDesc==NULL) return -EINVAL; + assert(fForwardedSegments.size()==fForwardedSegmentSources.size()); + if (fForwardedSegments.size()!=fForwardedSegmentSources.size()) return -EFAULT; + fForwardedSegmentSources.push_back(pSrcTask); + fForwardedSegments.push_back(AliHLTDataSegment(pBlockDesc->fPtr, pBlockDesc->fOffset, pBlockDesc->fSize)); + return 0; +} + AliHLTUInt8_t* AliHLTDataBuffer::GetTargetBuffer(int iMinSize) { // see header file for function documentation @@ -309,11 +359,14 @@ int AliHLTDataBuffer::SetSegments(AliHLTUInt8_t* pTgt, AliHLTComponentBlockData* // This function has to model the behavior of PubSub // For output blocks only the fOffset value is used, this must be the offset // relative to the output pointer. fPtr must be either NULL or the output - // pointer + // pointer. In either case it is 'ignored' and set to the beginning of the + // data buffer if (arrayBlockData[i].fPtr==NULL || arrayBlockData[i].fPtr==*fpBuffer) { + arrayBlockData[i].fPtr=*fpBuffer; if (arrayBlockData[i].fOffset+arrayBlockData[i].fSize<=fpBuffer->GetUsedSize()) { segment.fSegmentOffset=arrayBlockData[i].fOffset; + segment.fPtr=(AliHLTUInt8_t*)arrayBlockData[i].fPtr; segment.fSegmentSize=arrayBlockData[i].fSize; segment.fDataType=arrayBlockData[i].fDataType; segment.fSpecification=arrayBlockData[i].fSpecification; @@ -498,6 +551,11 @@ int AliHLTDataBuffer::ResetDataBuffer() AliHLTRawBuffer* pBuffer=fpBuffer; fpBuffer=NULL; + // cleanup forwarded segment lists + assert(fForwardedSegments.size()==0); + fForwardedSegments.clear(); + fForwardedSegmentSources.clear(); + // cleanup consumer states AliHLTConsumerDescriptorPList::iterator desc; // if (GetNofPendingConsumers()>0) { diff --git a/HLT/BASE/AliHLTDataBuffer.h b/HLT/BASE/AliHLTDataBuffer.h index 0e3702b3083..280eab9163e 100644 --- a/HLT/BASE/AliHLTDataBuffer.h +++ b/HLT/BASE/AliHLTDataBuffer.h @@ -25,10 +25,13 @@ #include "AliHLTComponent.h" class AliHLTConsumerDescriptor; +class AliHLTTask; /** list of AliHLTConsumerDescriptor pointers */ typedef vector AliHLTConsumerDescriptorPList; +typedef AliHLTUInt8_t* AliHLTUInt8Pointer_t; + /** * @class AliHLTDataBuffer * @brief Handling of data buffers for the HLT. @@ -115,12 +118,24 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging * The method is used by the consumer component. * @param pBlockDesc descriptor of the data segment * @param pConsumer the component which subscribes to the buffer + * @param pOwnerTask task owning this buffer * @return: >0 if success, negative error code if failed
* -EACCESS the consumer state can not be changed (de-activated) * -ENOENT consumer has not subscribed to the buffer
* -EINVAL invalid parameter
*/ - int Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTComponent* pConsumer); + int Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTComponent* pConsumer, + const AliHLTTask* pOwnerTask); + + /** + * Register an input data block for forwarding. + * Consumer of this data buffer subscribe to forwarded data blocks in te same way. + * Forwarded data blocks are released when the last consumer has released the + * blocks. + * @param pSrcTask original source task of the data block + * @param pBlockDesc descriptor of the data segment + */ + int Forward(AliHLTTask* pSrcTask, AliHLTComponentBlockData* pBlockDesc); /** * Get a target buffer of minimum size iMinSize. @@ -211,31 +226,64 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging * @brief Descriptor of a data segment within the buffer. */ class AliHLTDataSegment { - friend class AliHLTDataBuffer; - friend class AliHLTConsumerDescriptor; + friend class AliHLTDataBuffer; + friend class AliHLTConsumerDescriptor; public: AliHLTDataSegment() : - fDataType(), + fDataType(kAliHLTVoidDataType), + fPtr(NULL), fSegmentOffset(0), fSegmentSize(0), fSpecification(0) { - memset(&fDataType, 0, sizeof(AliHLTComponentDataType)); } - AliHLTDataSegment(AliHLTUInt32_t offset, AliHLTUInt32_t size) + + AliHLTDataSegment(AliHLTUInt8_t* ptr, AliHLTUInt32_t offset, AliHLTUInt32_t size) + : + fDataType(kAliHLTVoidDataType), + fPtr(ptr), + fSegmentOffset(offset), + fSegmentSize(size), + fSpecification(0) + { + } + + AliHLTDataSegment(void* ptr, AliHLTUInt32_t offset, AliHLTUInt32_t size) : - fDataType(), + fDataType(kAliHLTVoidDataType), + fPtr((AliHLTUInt8_t*)ptr), fSegmentOffset(offset), fSegmentSize(size), fSpecification(0) { - memset(&fDataType, 0, sizeof(AliHLTComponentDataType)); } + AliHLTDataSegment(void* ptr, AliHLTUInt32_t offset, AliHLTUInt32_t size, AliHLTComponentDataType dt, AliHLTUInt32_t spec) + : + fDataType(dt), + fPtr((AliHLTUInt8_t*)ptr), + fSegmentOffset(offset), + fSegmentSize(size), + fSpecification(spec) + { + } + + AliHLTUInt8_t* GetPtr() const {return (AliHLTUInt8_t*)*this;} + + AliHLTUInt32_t GetSize() const {return fSegmentSize;} + + int operator==(const AliHLTDataSegment& seg) const + { + return (fPtr+fSegmentOffset==seg.fPtr+seg.fSegmentOffset) && (fSegmentSize==seg.fSegmentSize); + } + operator AliHLTUInt8_t*() const {return fPtr+fSegmentOffset;} + private: /** the data type of this segment */ AliHLTComponentDataType fDataType; // see above + /** pointer to the buffer */ + AliHLTUInt8Pointer_t fPtr; //!transient /** offset in byte within the data buffer */ AliHLTUInt32_t fSegmentOffset; // see above /** size of the actual content */ @@ -373,6 +421,12 @@ class AliHLTDataBuffer : public TObject, public AliHLTLogging // flags indicating the state of the buffer AliHLTUInt32_t fFlags; // see above + /** list of tasks with forwarded data blocks */ + vector fForwardedSegmentSources; //! transient + + /** list of forwarded block descriptors */ + vector fForwardedSegments; //! transient + ////////////////////////////////////////////////////////////////////////////// // global buffer handling, internal use only diff --git a/HLT/BASE/AliHLTTask.cxx b/HLT/BASE/AliHLTTask.cxx index 6a57a3476be..2e1dacd80e7 100644 --- a/HLT/BASE/AliHLTTask.cxx +++ b/HLT/BASE/AliHLTTask.cxx @@ -33,6 +33,7 @@ using namespace std; #endif #include +#include #include #include #include "AliHLTTask.h" @@ -438,7 +439,7 @@ int AliHLTTask::ProcessTask(Int_t eventNo) int iInputDataVolume=0; AliHLTTask* pSrcTask=NULL; - TList subscribedTaskList; + AliHLTTaskPList subscribedTaskList; TObjLink* lnk=fListDependencies.FirstLink(); // subscribe to all source tasks @@ -464,7 +465,7 @@ int AliHLTTask::ProcessTask(Int_t eventNo) iInputDataVolume+=fBlockDataArray[i+iSourceDataBlock].fSize; // put the source task as many times into the list as it provides data blocks // makes the bookkeeping for the data release easier - subscribedTaskList.Add(pSrcTask); + subscribedTaskList.push_back(pSrcTask); } HLTDebug("Task %s (%p) successfully subscribed to %d data block(s) of task %s (%p)", GetName(), this, iResult, pSrcTask->GetName(), pSrcTask); iSourceDataBlock+=iResult; @@ -515,8 +516,25 @@ int AliHLTTask::ProcessTask(Int_t eventNo) if (pTgtBuffer!=NULL || iOutputDataSize==0) { iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd); HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt); - if (iResult>=0 && pTgtBuffer && outputBlocks) { - iResult=fpDataBuffer->SetSegments(pTgtBuffer, outputBlocks, outputBlockCnt); + if (iResult>=0 && outputBlocks) { + AliHLTComponentBlockDataList segments; + for (int oblock=0; oblockGetName(), pSrcTask, fpDataBuffer); + fpDataBuffer->Forward(subscribedTaskList[iblock], &fBlockDataArray[iblock]); + subscribedTaskList[iblock]=NULL; // not to be released in the loop further down + break; + } + } + if (iblock==evtData.fBlockCnt) segments.push_back(outputBlocks[oblock]); + } + if (pTgtBuffer && segments.size()>0) { + iResult=fpDataBuffer->SetSegments(pTgtBuffer, &segments[0], segments.size()); + } delete [] outputBlocks; outputBlocks=NULL; outputBlockCnt=0; } else { fpDataBuffer->Reset(); @@ -530,9 +548,9 @@ int AliHLTTask::ProcessTask(Int_t eventNo) // now release all buffers which we have subscribed to iSourceDataBlock=0; - lnk=subscribedTaskList.FirstLink(); - while (lnk) { - pSrcTask=(AliHLTTask*)lnk->GetObject(); + AliHLTTaskPList::iterator element; + while ((element=subscribedTaskList.begin())!=subscribedTaskList.end()) { + pSrcTask=*element; if (pSrcTask) { int iTempRes=0; if ((iTempRes=pSrcTask->Release(&fBlockDataArray[iSourceDataBlock], this))>=0) { @@ -540,15 +558,11 @@ int AliHLTTask::ProcessTask(Int_t eventNo) } else { HLTError("Task %s (%p): realease of task %s (%p) failed with error %d", GetName(), this, pSrcTask->GetName(), pSrcTask, iTempRes); } - } else { - HLTFatal("task %s (%p): internal error in ROOT list handling", GetName(), this); - if (iResult>=0) iResult=-EFAULT; } - subscribedTaskList.Remove(lnk); - lnk=subscribedTaskList.FirstLink(); + subscribedTaskList.erase(element); iSourceDataBlock++; } - if (subscribedTaskList.GetSize()>0) { + if (subscribedTaskList.size()>0) { HLTError("task %s (%p): could not release all data buffers", GetName(), this); } } else { @@ -621,7 +635,7 @@ int AliHLTTask::Release(AliHLTComponentBlockData* pBlockDesc, const AliHLTTask* int iResult=0; if (pConsumerTask && pBlockDesc) { if (fpDataBuffer) { - iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent()); + iResult=fpDataBuffer->Release(pBlockDesc, pConsumerTask->GetComponent(), this); } else { HLTFatal("internal data buffer missing"); iResult=-EFAULT; diff --git a/HLT/BASE/AliHLTTask.h b/HLT/BASE/AliHLTTask.h index 87f76dde098..b528f0c46b0 100644 --- a/HLT/BASE/AliHLTTask.h +++ b/HLT/BASE/AliHLTTask.h @@ -19,6 +19,7 @@ // or // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt +#include #include #include #include "AliHLTDataTypes.h" @@ -29,6 +30,9 @@ struct AliHLTComponentBlockData; class AliHLTComponent; class AliHLTComponentHandler; class AliHLTConfiguration; +class AliHLTTask; + +typedef vector AliHLTTaskPList; /******************************************************************************/ -- 2.43.0