1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2008/12/11 15:30:04 $
6 Version: $Revision: 1.38 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
33 * \brief Class bbtk::BlackBox : abstract black-box interface.
35 #include "bbtkBlackBox.h"
36 #include "bbtkPackage.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkFactory.h"
39 #include "bbtkBlackBoxOutputConnector.h"
41 #include "bbtkConfigurationFile.h"
42 #include "bbtkWxBlackBox.h"
52 static bool bbmgSomeBoxExecuting = false;
53 static bool bbmgFreezeExecution = false;
54 static std::set<BlackBox::WeakPointer> bbmgExecutionList;
56 //=========================================================================
57 BlackBox::Deleter::Deleter()
60 //=========================================================================
62 //=========================================================================
63 void BlackBox::Deleter::Delete(Object* p)
65 BlackBox* b = dynamic_cast<BlackBox*>(p);
68 bbtkInternalError("BlackBox::Deleter::Delete("<<p->GetObjectName()
70 <<"dynamic cast to BlackBox* failed !");
72 std::string name = p->GetObjectName();//b->bbGetNameWithParent();
73 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
76 BlackBoxDescriptor::WeakPointer desc = b->bbGetDescriptor();
77 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : deleting black box"<<std::endl);
81 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : releasing descriptor ["<<desc.lock()<<"]"<<std::endl);
85 Package::WeakPointer pack = desc.lock()->GetPackage();
88 Package::ReleaseBlackBoxDescriptor(pack,desc);
92 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor package expired (was not held by a package and the box was the last instance)"<<std::endl);
97 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor expired : nothing to do (was not held by a package or the box is a complex black box prototype)"<<std::endl);
99 bbtkDebugMessage("object",2,"<## BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
101 //=========================================================================
103 //=========================================================================
104 BlackBox::BlackBox(const std::string &name)
106 // bbmStatus(MODIFIED),
109 bbmBoxProcessMode("Pipeline"),
113 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
114 <<name<<"\")"<<std::endl);
115 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox(\""
116 <<name<<"\")"<<std::endl);
118 //=========================================================================
120 //=========================================================================
121 BlackBox::BlackBox(const BlackBox&)
124 //=========================================================================
125 BlackBox::BlackBox(BlackBox& from, const std::string &name)
127 // bbmStatus(from.bbmStatus),
130 bbmBoxProcessMode(from.bbmBoxProcessMode),
134 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox("
135 <<from.bbGetFullName()<<",\""
136 <<name<<"\")"<<std::endl);
137 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox("
138 <<from.bbGetFullName()<<",\""
139 <<name<<"\")"<<std::endl);
141 //=========================================================================
144 //=========================================================================
145 BlackBox::~BlackBox()
147 bbtkDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
149 this->bbDesallocateConnectors();
150 bbtkDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<<bbmName
153 //=========================================================================
157 //=========================================================================
158 std::string BlackBox::bbGetFullName() const
160 return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
162 //=========================================================================
166 //=========================================================================
167 /// Returns the name with the name of the parent prepended if any
168 std::string BlackBox::bbGetNameWithParent() const
170 if (bbmParent.lock())
172 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
179 //=========================================================================
181 //=========================================================================
182 /// Prints the Help on the BlackBox type
183 void BlackBox::bbGetHelp(bool full) const
185 bbGetDescriptor()->GetHelp(full);
187 //=========================================================================
190 //=========================================================================
191 /// Returns true if the UserBlackBox has an input of name name
192 bool BlackBox::bbHasInput(const std::string& name) const
194 bbtkDebugMessageInc("Kernel",8,
195 "BlackBox::bbHasInput(\""
196 <<name<<"\") ["<<bbGetFullName()<<"]"
198 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
199 != bbGetDescriptor()->GetInputDescriptorMap().end());
200 bbtkDebugDecTab("Kernel",8);
203 //=========================================================================
206 //=========================================================================
207 /// Returns true if the UserBlackBox has an output of name name
208 bool BlackBox::bbHasOutput(const std::string& name) const
210 bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
211 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
212 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
213 != bbGetDescriptor()->GetOutputDescriptorMap().end());
214 bbtkDebugDecTab("Kernel",8);
217 //=========================================================================
220 //=========================================================================
221 /// Gets the output type of a given name
222 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
224 bbtkDebugMessageInc("Kernel",8,
225 "BlackBox::bbGetOutputType(\""
226 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
227 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
228 bbtkDebugDecTab("Kernel",8);
231 //=========================================================================
233 //=========================================================================
234 /// Gets the input type of a given name
235 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
237 bbtkDebugMessageInc("Kernel",8,
238 "BlackBox::bbGetInputType(\""
239 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
240 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
241 bbtkDebugDecTab("Kernel",8);
244 //=========================================================================
247 //=========================================================================
248 /// Allocates the i/o connectors of the black box
249 void BlackBox::bbAllocateConnectors()
251 bbtkDebugMessageInc("Kernel",8,
252 "BlackBox::bbAllocateConnectors() ["
253 <<bbGetFullName()<<"]"
255 const BlackBoxDescriptor::InputDescriptorMapType& imap
256 = bbGetDescriptor()->GetInputDescriptorMap();
257 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
258 for ( i = imap.begin(); i != imap.end(); ++i )
260 bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
261 bbGetInputConnectorMap()[i->second->GetName()]
262 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
264 const BlackBoxDescriptor::OutputDescriptorMapType& omap
265 = bbGetDescriptor()->GetOutputDescriptorMap();
266 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
267 for ( o = omap.begin(); o != omap.end(); ++o )
269 bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
270 bbGetOutputConnectorMap()[o->second->GetName()]
271 = new BlackBoxOutputConnector();
273 bbtkDebugDecTab("Kernel",8);
275 //=========================================================================
278 //=========================================================================
279 /// Desallocates the i/o connectors of the black box
280 void BlackBox::bbDesallocateConnectors()
282 bbtkDebugMessageInc("Kernel",8,
283 "BlackBox::bbDesallocateConnectors()"
286 InputConnectorMapType::const_iterator i;
287 for ( i = bbGetInputConnectorMap().begin();
288 i != bbGetInputConnectorMap().end(); ++i )
290 bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
293 OutputConnectorMapType::const_iterator o;
294 for ( o = bbGetOutputConnectorMap().begin();
295 o != bbGetOutputConnectorMap().end(); ++o )
297 bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
301 bbtkDebugDecTab("Kernel",8);
304 //=========================================================================
307 //=========================================================================
308 /// Copies the input / output values from another box
309 void BlackBox::bbCopyIOValues(BlackBox& from)
311 bbtkDebugMessageInc("Kernel",1,
312 "BlackBox::bbCopyIOValues("
313 <<from.bbGetFullName()<<") ["
314 <<bbGetFullName()<<"]"<<std::endl);
315 // copies the input values
316 const BlackBoxDescriptor::InputDescriptorMapType& imap
317 = bbGetDescriptor()->GetInputDescriptorMap();
318 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
319 for ( i = imap.begin(); i != imap.end(); ++i )
321 if (! i->second->GetCopyConstruct() ) continue;
322 std::string input = i->second->GetName();
323 bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
324 this->bbSetInput(input, from.bbGetInput(input) );
326 // copies the output values
327 const BlackBoxDescriptor::OutputDescriptorMapType& omap
328 = bbGetDescriptor()->GetOutputDescriptorMap();
329 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
330 for ( o = omap.begin(); o != omap.end(); ++o )
332 if (! o->second->GetCopyConstruct() ) continue;
333 std::string output = o->second->GetName();
334 bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
335 this->bbSetOutput(output, from.bbGetOutput(output) );
338 bbtkDebugDecTab("Kernel",9);
341 //=========================================================================
345 //=========================================================================
346 bool BlackBox::bbCanReact() const
348 return ( bbGlobalGetSomeBoxExecuting()
350 || Wx::IsSomeWindowAlive()
354 //=========================================================================
358 //=========================================================================
359 /// User overloadable destruction method of a black box
360 void BlackBox::bbUserDelete()
362 bbtkDebugMessage("process",5,
363 "=> BlackBox::bbUserDelete() ["
364 <<bbGetFullName()<<"]"
365 <<" : not overloaded; using standard deletion"
369 //=========================================================================
372 //=========================================================================
373 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
375 const std::string& p = bbmBoxProcessMode;
377 (p == "P") || (p == "p") ||
378 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
380 (p == "A") || (p == "a") ||
381 (p == "Always") || (p == "always") ) return Always;
383 (p == "R") || (p == "r") ||
384 (p == "Reactive") || (p == "reactive") ) return Reactive;
385 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
386 <<"' unknown. Possible values : "
387 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
388 <<"'1'/'A'/'a'/'Always'/'always' | "
389 <<"'2'/'R'/'r'/'Reactive'/'reactive'"<<std::endl);
391 //=========================================================================
393 //=========================================================================
394 bool BlackBox::bbBoxProcessModeIsReactive() const
396 return (bbGetBoxProcessModeValue() == Reactive);
398 //=========================================================================
400 //=========================================================================
401 bool BlackBox::bbBoxProcessModeIsAlways() const
403 return (bbGetBoxProcessModeValue() == Always);
405 //=========================================================================
410 //=========================================================================
411 void BlackBox::bbAddOutputObserver(const std::string& output,
412 OutputChangeCallbackType f)
414 bbGetOutputConnector(output).AddChangeObserver(f);
416 //=========================================================================
418 //=========================================================================
419 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
420 OutputChangeCallbackType f)
422 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
424 //=========================================================================
428 //=========================================================================
429 /// Sets the ChangeTime of input
430 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
433 bbtkDebugMessage("change",1,
434 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
435 <<bbGetFullName()<<"]"<<std::endl);
437 // If new time is greater than old one
438 if ( c->SetChangeTime(t) )
440 bool was_up_to_date = bbIsUpToDate();
441 // If new time is greater than the old max time of inputs
442 if ( mMaxInputChangeTime.Set(t) )
444 // If the box turned out-of-date
445 if ( was_up_to_date && bbIsOutOfDate() )
448 if ( ( bbBoxProcessModeIsReactive() ||
449 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
452 bbtkDebugMessage("change",2,
455 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
457 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
459 // Have to propagate the modification to aval boxes
460 OutputConnectorMapType::iterator i;
461 for (i = bbGetOutputConnectorMap().begin();
462 i != bbGetOutputConnectorMap().end();
465 i->second->SetChangeTime(t);
467 // update the MinOutputChangeTime
468 mMinOutputChangeTime.Set(t);
473 //=========================================================================
475 //=========================================================================
476 /// Sets the ChangeTime of output
477 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
480 bbtkDebugMessage("change",1,
481 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
482 <<bbGetFullName()<<"]"<<std::endl);
486 // c->GetChangeTime() = t;
487 // bbUpdateMinOutputChangeTime(t);
491 //=========================================================================
495 //=========================================================================
496 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
500 if ( t > mMaxInputChangeTime )
502 mMaxInputChangeTime = t;
503 if ( mMinOutputChangeTime > mMaxInputChangeTime )
510 //=========================================================================
512 //=========================================================================
513 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
515 ChangeTime old = mMinOutputChangeTime;
516 mMinOutputChangeTime = MAXLONG;
517 OutputConnectorMapType::iterator i;
518 for (i = bbGetOutputConnectorMap.begin();
519 i != bbGetOutputConnectorMap.end();
522 if (i->second->GetChangeTime() < mMinOutputChangeTime)
523 mMinOutputChangeTime = i->second->GetChangeTime();
525 if ( mMinOutputChangeTime < old )
530 //=========================================================================
533 //=========================================================================
534 /// Signals that the BlackBox has been modified through
535 /// the input connector c
536 /// and propagates it downward
537 /// ** NOT USER INTENDED **
538 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
541 bbtkDebugMessageInc("change",5,
542 "=> BlackBox::bbSetStatusAndPropagate(input,"
543 <<GetIOStatusString(s)<<") ["
544 <<bbGetFullName()<<"]"<<std::endl);
546 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
548 OutputConnectorMapType::const_iterator o;
549 for ( o = bbGetOutputConnectorMap().begin();
550 o != bbGetOutputConnectorMap().end(); ++o )
552 if (o->second->GetStatus()==UPTODATE)
554 o->second->SetStatus(OUTOFDATE);
555 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
559 if ( ( bbBoxProcessModeIsReactive() ||
560 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
563 bbtkDebugMessage("change",2,
564 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
565 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
567 bbtkDebugMessageInc("change",5,
568 "<= BlackBox::bbSetStatusAndPropagate(input) ["
569 <<bbGetFullName()<<"]"<<std::endl);
571 //=========================================================================
574 //=========================================================================
575 void BlackBox::bbSignalOutputModification(bool reaction)
577 bbtkDebugMessageInc("change",5,
578 "=> BlackBox::bbSignalOutputModification("
580 <<bbGetFullName()<<"]"<<std::endl);
582 OutputConnectorMapType::iterator i;
583 for ( i = bbGetOutputConnectorMap().begin();
584 i != bbGetOutputConnectorMap().end(); ++i)
586 // std::cout << "Stat = "
587 //<<GetIOStatusString(i->second->GetStatus())
589 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
590 // See bbtkSampleOutputObserver
591 // if (i->second->GetStatus()==UPTODATE)
593 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
597 if (reaction) bbGlobalProcessExecutionList();
599 bbtkDebugMessageDec("change",5,
600 "<= BlackBox::bbSignalOutputModification() ["
601 <<bbGetFullName()<<"]"<<std::endl);
604 //=========================================================================
605 //=========================================================================
606 void BlackBox::bbSignalOutputModification(const std::string& output,
609 bbtkDebugMessageInc("change",5,
610 "=> BlackBox::bbSignalOutputModification("
611 <<output<<","<<reaction<<") ["
612 <<bbGetFullName()<<"]"<<std::endl);
614 OutputConnectorMapType::iterator i =
615 bbGetOutputConnectorMap().find(output);
618 if ( i == bbGetOutputConnectorMap().end() )
620 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
623 // if (i->second->GetStatus()==UPTODATE)
625 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
626 // Has to notify the output "BoxChange" also
627 if (output != "BoxChange")
629 i = bbGetOutputConnectorMap().find("BoxChange");
630 if ( i != bbGetOutputConnectorMap().end() )
632 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
635 if (reaction) bbGlobalProcessExecutionList();
638 bbtkDebugMessageDec("change",5,
639 "<= BlackBox::bbSignalOutputModification("
641 <<bbGetFullName()<<"]"<<std::endl);
644 //=========================================================================
645 //=========================================================================
646 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
649 bbtkDebugMessageInc("change",5,
650 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
651 <<bbGetFullName()<<"]"<<std::endl);
652 OutputConnectorMapType::iterator i;
653 std::vector<std::string>::const_iterator o;
654 bool changed = false;
655 for (o=output.begin();o!=output.end();++o)
657 // the output "BoxChange" must be signaled **AFTER** all others
658 if (*o == "BoxChange") continue;
659 // Look for the connector
660 i = bbGetOutputConnectorMap().find(*o);
661 if ( i == bbGetOutputConnectorMap().end() )
663 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
666 // if (i->second->GetStatus()==UPTODATE)
668 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
672 // Has to notify the output "BoxChange" also
673 i = bbGetOutputConnectorMap().find("BoxChange");
674 if ( changed && (i != bbGetOutputConnectorMap().end()))
676 // if (i->second->GetStatus()==UPTODATE)
678 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
679 if (reaction) bbGlobalProcessExecutionList();
683 bbtkDebugMessageDec("change",5,
684 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
685 <<bbGetFullName()<<"]"<<std::endl);
688 //=========================================================================
696 //=========================================================================
697 /// Main processing method of the box.
698 void BlackBox::bbExecute(bool force)
700 bbtkDebugMessageInc("process",2,
701 "=> BlackBox::bbExecute("<<(int)force<<") ["
702 <<bbGetFullName()<<"]"<<std::endl);
704 // If already executing : return
706 if (bbGetExecuting())
708 bbtkDebugMessage("process",2,
709 " -> already executing : abort"<<std::endl);
714 // If execution frozen : return
715 if (bbGlobalGetFreezeExecution())
717 bbtkDebugMessage("process",2,
718 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
723 // If force is true then update is triggered even if the box is UPTODATE
724 // if (force) bbSetModifiedStatus();
726 // Calls the main recursive execution method
727 bbRecursiveExecute(Connection::Pointer());
729 bbtkDebugMessageDec("process",2,
730 "<= BlackBox::bbExecute() ["
731 <<bbGetFullName()<<"]"<<std::endl);
733 //=========================================================================
736 //=========================================================================
737 /// Main recursive processing method of the box.
738 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
740 bbtkDebugMessageInc("process",3,
741 "=> BlackBox::bbRecursiveExecute("
742 <<(caller?caller->GetFullName():"0")<<") ["
743 <<bbGetFullName()<<"]"<<std::endl);
745 // If already executing : return
746 if (bbGetExecuting())
748 bbtkDebugMessage("process",3,
749 " -> already executing : abort"<<std::endl);
753 bbSetExecuting(true);
754 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
755 bbGlobalSetSomeBoxExecuting(true);
757 // Updates its inputs
758 IOStatus s = bbUpdateInputs();
760 if ( (s != UPTODATE) ||
761 bbBoxProcessModeIsAlways() )
763 // Displays the window (WxBlackbox)
764 // bbShowWindow(caller);
766 // Actual processing (virtual)
770 // Update the I/O statuses
771 bbComputePostProcessStatus();
775 // Test output status...
776 OutputConnectorMapType::iterator o;
777 for ( o = bbGetOutputConnectorMap().begin();
778 o!= bbGetOutputConnectorMap().end(); ++o)
780 if (o->second->GetStatus() != UPTODATE)
782 bbtkWarning("BlackBox::bbRecursiveExecute ["
784 <<"] : all inputs are Up-to-date but output '"
785 <<o->first<<"' is Out-of-date ???");
789 bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
793 bbtkDebugMessage("process",3,
794 "<= BlackBox::bbRecursiveExecute() ["
795 <<bbGetFullName()<<"]"<<std::endl);
797 bbSetExecuting(false);
798 bbGlobalSetSomeBoxExecuting(wasExecuting);
803 //=========================================================================
809 //=========================================================================
810 /// Updates the BlackBox inputs
811 /// Calls RecursiveExecute on all BlackBoxInputConnector
812 /// \returns The maximum of final IOStatus after each input update
813 IOStatus BlackBox::bbUpdateInputs()
815 bbtkDebugMessageInc("process",4,
816 "=> BlackBox::bbUpdateInputs() ["
817 <<bbGetFullName()<<"]"
820 IOStatus s = UPTODATE;
822 InputConnectorMapType::iterator i;
823 for ( i = bbGetInputConnectorMap().begin();
824 i!= bbGetInputConnectorMap().end(); ++i)
826 // if (i->first=="WinHide") continue;
827 // If input type is Void : no recurse
828 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
831 bbtkDebugMessageDec("change",2,
832 bbGetName()<<"."<<i->first
833 <<" ["<<i->second<<"] "
834 <<" status before update = '"
835 <<GetIOStatusString(i->second->GetStatus())
837 i->second->RecursiveExecute();
838 IOStatus t = i->second->GetStatus();
840 bbtkDebugMessageDec("change",2,
841 bbGetName()<<"."<<i->first
842 <<" ["<<i->second<<"] "
843 <<" status before process = '"
844 <<GetIOStatusString(i->second->GetStatus())
848 bbtkDebugMessageDec("process",4,
849 "<= BlackBox::bbUpdateInputs() ["
850 <<bbGetFullName()<<"]"
856 //=========================================================================
858 //==================================================================
859 /// Computes the final IOStatus of inputs and outputs after processing
860 void BlackBox::bbComputePostProcessStatus()
862 bbtkDebugMessageInc("process",4,
863 "=> BlackBox::bbComputePostProcessStatus() ["
864 <<bbGetFullName()<<"]"
867 IOStatus new_output_status = UPTODATE;
868 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
870 // Update the input statuses
871 InputConnectorMapType::iterator i;
872 for ( i = bbGetInputConnectorMap().begin();
873 i!= bbGetInputConnectorMap().end(); ++i)
875 IOStatus t = i->second->GetStatus();
876 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
877 // A previously MODIFIED status turns to UPTODATE
878 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
879 bbtkDebugMessage("change",2,
880 bbGetName()<<"."<<i->first<<" : "
881 << GetIOStatusString(t) << " -> "
882 << GetIOStatusString(i->second->GetStatus())
885 bbtkDebugMessage("change",2,
886 bbGetName()<<" new output status : "
887 << GetIOStatusString(new_output_status)
889 // Update the output statuses
890 OutputConnectorMapType::iterator o;
891 for ( o = bbGetOutputConnectorMap().begin();
892 o!= bbGetOutputConnectorMap().end(); ++o)
894 o->second->SetStatus(new_output_status);
897 bbtkDebugMessageInc("process",4,
898 "<= BlackBox::bbComputePostProcessStatus() ["
899 <<bbGetFullName()<<"]"
903 //==================================================================
905 //=========================================================================
906 /// Connects the input <name> to the connection c
907 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
909 bbtkDebugMessage("connection",2,
910 "==> BlackBox::bbConnectInput(\""
911 <<name<<"\","<<c->GetFullName()<<") ["
912 <<bbGetFullName()<<"]"
916 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
917 if (i==bbGetInputConnectorMap().end())
919 bbtkError("no input called '"<<name<<"'");
921 i->second->SetConnection(c);
922 // The input *MUST* be set OUTOFDATE to update its input on next execution
923 bbSetStatusAndPropagate(i->second,OUTOFDATE);
925 bbtkDebugMessage("connection",2,
926 "<== BlackBox::bbConnectInput(\""
927 <<name<<"\","<<c->GetFullName()<<") ["
928 <<bbGetFullName()<<"]"
932 //=========================================================================
935 //=========================================================================
936 /// Connects the output <name> to the connection c
937 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
939 bbtkDebugMessage("connection",2,
940 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
941 <<c->GetFullName()<<") ["
942 <<bbGetFullName()<<"]"<<std::endl);
944 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
945 if (i==bbGetOutputConnectorMap().end())
947 bbtkError("no output called '"<<name<<"'");
949 i->second->SetConnection(c);
951 bbtkDebugMessage("connection",2,
952 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
953 <<c->GetFullName()<<") ["
954 <<bbGetFullName()<<"]"<<std::endl);
957 //=========================================================================
960 //=========================================================================
961 /// Disconnects the input <name> from the connection c
962 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
965 bbtkDebugMessage("connection",2,
966 "==> BlackBox::bbDisconnectInput(\""<<name
967 <<"\","<<c->GetFullName()<<") ["
968 <<bbGetFullName()<<"]"
974 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
978 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
979 if (i==bbGetInputConnectorMap().end())
981 bbtkError("no input called '"<<name<<"'");
983 i->second->UnsetConnection(c);
985 bbtkDebugMessage("connection",2,
986 "<== BlackBox::bbDisconnectInput(\""<<name
987 <<"\","<<c->GetFullName()<<") ["
988 <<bbGetFullName()<<"]"
992 //=========================================================================
995 //=========================================================================
996 /// Disconnects the output <name> from the connection c
997 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
999 bbtkDebugMessage("connection",2,
1000 "==> BlackBox::bbDisconnectOutput(\""<<name
1001 <<"\","<<c->GetFullName()<<") ["
1002 <<bbGetFullName()<<"]"
1007 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1011 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1012 if (i==bbGetOutputConnectorMap().end())
1014 bbtkError("no output called '"<<name<<"'");
1016 i->second->UnsetConnection(c);
1018 bbtkDebugMessage("connection",2,
1019 "<== BlackBox::bbDisconnectOutput(\""<<name
1020 <<"\","<<c->GetFullName()<<") ["
1021 <<bbGetFullName()<<"]"
1024 //=========================================================================
1027 //=========================================================================
1029 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1031 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1033 //=========================================================================
1036 //=========================================================================
1037 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1040 // Looks for the adaptor
1041 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1044 Package::Pointer p = bbGetDescriptor()->GetPackage();
1045 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1047 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1048 BlackBox::Pointer a;
1052 bbGetOutputType(output),
1053 typeid(std::string),
1055 } catch (bbtk::Exception e)
1060 a->bbSetInput("In",bbGetOutput(output));
1062 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1064 v="? (no adaptor found)";
1069 v="? (no factory found)";
1075 v = bbGetOutput(output).unsafe_get<std::string>() ;
1079 //=========================================================================
1081 //=========================================================================
1082 std::string BlackBox::bbGetInputAsString( const std::string &input )
1085 // Looks for the adaptor
1086 if (bbGetInputType(input) != typeid(std::string))
1089 Package::Pointer p = bbGetDescriptor()->GetPackage();
1090 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1092 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1093 BlackBox::Pointer a;
1097 bbGetInputType(input),
1098 typeid(std::string),
1100 }catch (bbtk::Exception e)
1106 a->bbSetInput("In",bbGetInput(input));
1108 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1112 v="? (no adaptor found)";
1117 v="? (no factory found)";
1122 v = bbGetInput(input).unsafe_get<std::string>() ;
1126 //=======================================================================
1128 //=======================================================================
1129 // Replaces substrings "<" by "["
1130 void SubsBrackets ( std::string& s )
1132 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1133 std::string ss("<");
1134 std::string::size_type pos = 0;
1136 std::string cr("[");
1137 while ( pos != std::string::npos )
1139 // std::cout << "*** find one "<<std::endl;
1140 s.replace(pos,1,cr.c_str(),1);
1141 pos = s.find(ss, pos);
1147 while ( pos != std::string::npos )
1149 // std::cout << "*** find one "<<std::endl;
1150 s.replace(pos,1,cr.c_str(),1);
1151 pos = s.find(ss, pos);
1157 while ( pos != std::string::npos )
1159 // std::cout << "*** find one "<<std::endl;
1160 s.replace(pos,1,cr.c_str(),1);
1161 pos = s.find(ss, pos);
1162 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1164 //=======================================================================
1166 //=========================================================================
1167 /// Write Graphviz-dot description in file
1168 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1169 BlackBox::Pointer parentblackbox,
1170 int detail, int level,
1171 bool instanceOrtype,
1172 bool relative_link )
1175 InputConnectorMapType::iterator i;
1177 std::string labelStr;
1178 std::string valueStr("");
1181 labelStr = bbGetName() ;
1183 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1185 labelStr = bbGetName();
1186 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1189 SubsBrackets(labelStr);
1192 labelStr = labelStr + " | {{ ";
1193 std::string tempStrTypeName;
1196 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1200 labelStr=labelStr+" | ";
1203 if (instanceOrtype==true)
1205 valueStr = this->bbGetInputAsString(i->first) + " = ";
1207 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1208 tempStrTypeName=id->GetTypeName();
1209 SubsBrackets(tempStrTypeName);
1210 std::string Name(i->first);
1212 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1214 labelStr=labelStr+ " } | {";
1216 OutputConnectorMapType::iterator ii;
1217 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1221 labelStr=labelStr+" | ";
1224 if (instanceOrtype==true)
1226 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1228 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1229 tempStrTypeName=id->GetTypeName();
1230 SubsBrackets(tempStrTypeName);
1231 std::string Name(ii->first);
1233 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1235 labelStr = labelStr+ " } }" ;
1239 bbWriteDotInputOutputName(ff,true,detail,level);
1240 std::string tmp ( bbGetTypeName() );
1244 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1246 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1248 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1249 // std::cout << labelStr << std::endl;
1252 if (GetThisPointer<BlackBox>()!=parentblackbox){
1253 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1257 Connection* con = i->second->GetConnection();
1259 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1260 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1262 a->bbWriteDotInputOutputName(ff,false,detail,level);
1265 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1268 b->bbWriteDotInputOutputName(ff,true,detail,level);
1271 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1273 fprintf(ff,"%s\n",";");
1277 } // if parentblackbox
1279 //=========================================================================
1284 //=========================================================================
1285 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1286 int detail, int level
1287 /*,Factory *factory*/ )
1290 if (this->bbGetDescriptor()->GetPackage())
1292 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1293 this->bbGetDescriptor()->GetPackage()->GetName()
1294 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1298 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1303 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1304 <<mMinOutputChangeTime<<"]"<<std::endl);
1308 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1309 <<mMinOutputChangeTime<<"]"<<std::endl);
1312 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1313 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1315 std::vector<std::string> iname;
1316 std::vector<std::string> ivalue;
1317 std::vector<std::string> iconn;
1318 std::vector<std::string> istatus;
1320 InputConnectorMapType::iterator i;
1321 unsigned int namelmax = 0;
1322 unsigned int valuelmax = 0;
1323 // unsigned int connlmax = 0;
1324 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1326 iname.push_back(i->first);
1327 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1328 ivalue.push_back(bbGetInputAsString(i->first));
1329 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1331 Connection* con = i->second->GetConnection();
1333 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1335 s += con->GetOriginalBlackBoxFromOutput();
1338 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1340 OutputConnectorMapType::iterator o;
1341 std::vector<std::string> oname;
1342 std::vector<std::string> ovalue;
1343 std::vector<std::vector<std::string> > oconn;
1344 std::vector<std::string> ostatus;
1345 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1347 oname.push_back(o->first);
1348 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1349 ovalue.push_back(bbGetOutputAsString(o->first));
1350 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1351 std::vector<std::string> ss;
1352 const std::vector<Connection*>& con
1353 = o->second->GetConnectionVector();
1354 std::vector<Connection*>::const_iterator c;
1355 for (c=con.begin();c!=con.end();++c)
1358 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1360 s += (*c)->GetOriginalBlackBoxToInput();
1363 oconn.push_back(ss);
1364 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1368 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1370 bbtkMessage("Help",1," * No inputs"<<std::endl);
1372 std::vector<std::string>::iterator i1,i2,i3,i4;
1373 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1374 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1375 ++i1,++i2,++i3,++i4)
1377 std::string name(*i1);
1379 name.append(1+namelmax-name.size(),' ');
1380 std::string value(*i2);
1382 value.append(1+valuelmax-value.size(),' ');
1384 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1387 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1388 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1392 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1394 bbtkMessage("Help",1," * No outputs"<<std::endl);
1396 std::vector<std::vector<std::string> >::iterator i5;
1398 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1399 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1400 ++i1,++i2,++i4,++i5)
1402 std::string name(*i1);
1404 name.append(1+namelmax-name.size(),' ');
1405 std::string value(*i2);
1407 value.append(1+valuelmax-value.size(),' ');
1409 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1412 std::string pref = " '"+name+" = '"+value;
1413 for (i3=i5->begin();i3!=i5->end();++i3)
1415 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1416 pref.replace(0,pref.size(),pref.size(),' ');
1419 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1423 //=========================================================================
1425 static bool bbmgGlobalProcessingExecutionList = false;
1427 //=========================================================================
1428 void BlackBox::bbGlobalProcessExecutionList()
1430 bbtkDebugMessageInc("process",3,
1431 "=> BlackBox::bbGlobalProcessExecutionList()"
1433 if (bbmgGlobalProcessingExecutionList)
1435 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1438 bbmgGlobalProcessingExecutionList = true;
1440 std::set<BlackBox::WeakPointer>::iterator i;
1441 while (bbmgExecutionList.size()>0)
1443 i = bbmgExecutionList.begin();
1444 BlackBox::WeakPointer p = *i;
1445 bbmgExecutionList.erase(i);
1448 bbtkDebugMessage("process",4,
1450 p.lock()->bbGetFullName()<<std::endl);
1451 p.lock()->bbExecute(true);
1455 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1459 bbmgExecutionList.clear();
1460 bbtkDebugMessageDec("process",3,
1461 "<= BlackBox::bbGlobalProcessExecutionList()"
1464 bbmgGlobalProcessingExecutionList = false;
1467 //=========================================================================
1469 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1471 return bbmgSomeBoxExecuting;
1474 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1476 bbmgSomeBoxExecuting = b;
1479 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1481 bbmgFreezeExecution = b;
1484 bool BlackBox::bbGlobalGetFreezeExecution()
1486 return bbmgFreezeExecution;
1489 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1491 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1492 if (bbmgGlobalProcessingExecutionList)
1494 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1496 bbmgExecutionList.insert(b);
1500 //=========================================================================
1502 //=========================================================================
1503 void BlackBox::Check(bool recursive)
1505 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1506 <<"] ... OK"<<std::endl);
1508 //=========================================================================
1510 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1512 bbtk::BlackBoxInputConnector *cc;
1513 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1514 if (cc->GetConnection()!=NULL)
1516 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1522 } // EO namespace bbtk