1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/03/30 14:42:16 $
6 Version: $Revision: 1.41 $
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 //=========================================================================
58 BlackBox::Deleter::Deleter()
61 //=========================================================================
63 //=========================================================================
64 void BlackBox::Deleter::Delete(Object* p)
66 BlackBox* b = dynamic_cast<BlackBox*>(p);
69 bbtkInternalError("BlackBox::Deleter::Delete("<<p->GetObjectName()
71 <<"dynamic cast to BlackBox* failed !");
73 std::string name = p->GetObjectName();//b->bbGetNameWithParent();
74 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
77 BlackBoxDescriptor::WeakPointer desc = b->bbGetDescriptor();
78 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : deleting black box"<<std::endl);
82 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : releasing descriptor"<<std::endl);
86 Package::WeakPointer pack = desc.lock()->GetPackage();
89 Package::ReleaseBlackBoxDescriptor(pack,desc);
93 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor package expired (was not held by a package and the box was the last instance)"<<std::endl);
98 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);
100 bbtkDebugMessage("object",2,"<## BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
102 //=========================================================================
104 //=========================================================================
105 BlackBox::BlackBox(const std::string &name)
107 // bbmStatus(MODIFIED),
110 bbmBoxProcessMode("Pipeline"),
114 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
115 <<name<<"\")"<<std::endl);
116 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox(\""
117 <<name<<"\")"<<std::endl);
119 //=========================================================================
121 //=========================================================================
122 BlackBox::BlackBox(const BlackBox&)
125 //=========================================================================
126 BlackBox::BlackBox(BlackBox& from, const std::string &name)
128 // bbmStatus(from.bbmStatus),
131 bbmBoxProcessMode(from.bbmBoxProcessMode),
135 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox("
136 <<from.bbGetFullName()<<",\""
137 <<name<<"\")"<<std::endl);
138 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox("
139 <<from.bbGetFullName()<<",\""
140 <<name<<"\")"<<std::endl);
142 //=========================================================================
145 //=========================================================================
146 BlackBox::~BlackBox()
148 bbtkDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
150 this->bbDesallocateConnectors();
151 bbtkDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<<bbmName
154 //=========================================================================
158 //=========================================================================
159 std::string BlackBox::bbGetFullName() const
161 return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
163 //=========================================================================
167 //=========================================================================
168 /// Returns the name with the name of the parent prepended if any
169 std::string BlackBox::bbGetNameWithParent() const
171 if (bbmParent.lock())
173 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
180 //=========================================================================
182 //=========================================================================
183 /// Prints the Help on the BlackBox type
184 void BlackBox::bbGetHelp(bool full) const
186 bbGetDescriptor()->GetHelp(full);
188 //=========================================================================
191 //=========================================================================
192 /// Returns true if the UserBlackBox has an input of name name
193 bool BlackBox::bbHasInput(const std::string& name) const
195 bbtkDebugMessageInc("Kernel",8,
196 "BlackBox::bbHasInput(\""
197 <<name<<"\") ["<<bbGetFullName()<<"]"
199 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
200 != bbGetDescriptor()->GetInputDescriptorMap().end());
201 bbtkDebugDecTab("Kernel",8);
204 //=========================================================================
207 //=========================================================================
208 /// Returns true if the UserBlackBox has an output of name name
209 bool BlackBox::bbHasOutput(const std::string& name) const
211 bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
212 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
213 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
214 != bbGetDescriptor()->GetOutputDescriptorMap().end());
215 bbtkDebugDecTab("Kernel",8);
218 //=========================================================================
221 //=========================================================================
222 /// Gets the output type of a given name
223 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
225 bbtkDebugMessageInc("Kernel",8,
226 "BlackBox::bbGetOutputType(\""
227 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
228 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
229 bbtkDebugDecTab("Kernel",8);
232 //=========================================================================
234 //=========================================================================
235 /// Gets the input type of a given name
236 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
238 bbtkDebugMessageInc("Kernel",8,
239 "BlackBox::bbGetInputType(\""
240 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
241 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
242 bbtkDebugDecTab("Kernel",8);
245 //=========================================================================
248 //=========================================================================
249 /// Allocates the i/o connectors of the black box
250 void BlackBox::bbAllocateConnectors()
252 bbtkDebugMessageInc("Kernel",8,
253 "BlackBox::bbAllocateConnectors() ["
254 <<bbGetFullName()<<"]"
256 const BlackBoxDescriptor::InputDescriptorMapType& imap
257 = bbGetDescriptor()->GetInputDescriptorMap();
258 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
259 for ( i = imap.begin(); i != imap.end(); ++i )
261 bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
262 bbGetInputConnectorMap()[i->second->GetName()]
263 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
265 const BlackBoxDescriptor::OutputDescriptorMapType& omap
266 = bbGetDescriptor()->GetOutputDescriptorMap();
267 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
268 for ( o = omap.begin(); o != omap.end(); ++o )
270 bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
271 bbGetOutputConnectorMap()[o->second->GetName()]
272 = new BlackBoxOutputConnector();
274 bbtkDebugDecTab("Kernel",8);
276 //=========================================================================
279 //=========================================================================
280 /// Desallocates the i/o connectors of the black box
281 void BlackBox::bbDesallocateConnectors()
283 bbtkDebugMessageInc("Kernel",8,
284 "BlackBox::bbDesallocateConnectors()"
287 InputConnectorMapType::const_iterator i;
288 for ( i = bbGetInputConnectorMap().begin();
289 i != bbGetInputConnectorMap().end(); ++i )
291 bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
294 OutputConnectorMapType::const_iterator o;
295 for ( o = bbGetOutputConnectorMap().begin();
296 o != bbGetOutputConnectorMap().end(); ++o )
298 bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
302 bbtkDebugDecTab("Kernel",8);
305 //=========================================================================
308 //=========================================================================
309 /// Copies the input / output values from another box
310 void BlackBox::bbCopyIOValues(BlackBox& from)
312 bbtkDebugMessageInc("Kernel",1,
313 "BlackBox::bbCopyIOValues("
314 <<from.bbGetFullName()<<") ["
315 <<bbGetFullName()<<"]"<<std::endl);
316 // copies the input values
317 const BlackBoxDescriptor::InputDescriptorMapType& imap
318 = bbGetDescriptor()->GetInputDescriptorMap();
319 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
320 for ( i = imap.begin(); i != imap.end(); ++i )
322 if (! i->second->GetCopyConstruct() ) continue;
323 std::string input = i->second->GetName();
324 bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
325 this->bbSetInput(input, from.bbGetInput(input) );
327 // copies the output values
328 const BlackBoxDescriptor::OutputDescriptorMapType& omap
329 = bbGetDescriptor()->GetOutputDescriptorMap();
330 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
331 for ( o = omap.begin(); o != omap.end(); ++o )
333 if (! o->second->GetCopyConstruct() ) continue;
334 std::string output = o->second->GetName();
335 bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
336 this->bbSetOutput(output, from.bbGetOutput(output) );
339 bbtkDebugDecTab("Kernel",9);
342 //=========================================================================
346 //=========================================================================
347 bool BlackBox::bbCanReact() const
349 return ( bbGlobalGetSomeBoxExecuting()
351 || Wx::IsSomeWindowAlive()
355 //=========================================================================
359 //=========================================================================
360 /// User overloadable destruction method of a black box
361 void BlackBox::bbUserDelete()
363 bbtkDebugMessage("process",5,
364 "=> BlackBox::bbUserDelete() ["
365 <<bbGetFullName()<<"]"
366 <<" : not overloaded; using standard deletion"
370 //=========================================================================
373 //=========================================================================
374 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
376 const std::string& p = bbmBoxProcessMode;
378 (p == "P") || (p == "p") ||
379 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
381 (p == "A") || (p == "a") ||
382 (p == "Always") || (p == "always") ) return Always;
384 (p == "R") || (p == "r") ||
385 (p == "Reactive") || (p == "reactive") ) return Reactive;
388 (p == "F") || (p == "f") ||
389 (p == "Flash") || (p == "flash") ) return Flash;
391 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
392 <<"' unknown. Possible values : "
393 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
394 <<"'1'/'A'/'a'/'Always'/'always' | "
395 <<"'2'/'R'/'r'/'Reactive'/'reactive'"
396 // <<"'3'/'F'/'f'/'Flash'/'flash'"
399 //=========================================================================
401 //=========================================================================
402 bool BlackBox::bbBoxProcessModeIsReactive() const
404 return (bbGetBoxProcessModeValue() == Reactive);
406 //=========================================================================
408 //=========================================================================
409 bool BlackBox::bbBoxProcessModeIsAlways() const
411 return (bbGetBoxProcessModeValue() == Always);
413 //=========================================================================
418 //=========================================================================
419 void BlackBox::bbAddOutputObserver(const std::string& output,
420 OutputChangeCallbackType f)
422 bbGetOutputConnector(output).AddChangeObserver(f);
424 //=========================================================================
426 //=========================================================================
427 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
428 OutputChangeCallbackType f)
430 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
432 //=========================================================================
436 //=========================================================================
437 /// Sets the ChangeTime of input
438 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
441 bbtkDebugMessage("change",1,
442 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
443 <<bbGetFullName()<<"]"<<std::endl);
445 // If new time is greater than old one
446 if ( c->SetChangeTime(t) )
448 bool was_up_to_date = bbIsUpToDate();
449 // If new time is greater than the old max time of inputs
450 if ( mMaxInputChangeTime.Set(t) )
452 // If the box turned out-of-date
453 if ( was_up_to_date && bbIsOutOfDate() )
456 if ( ( bbBoxProcessModeIsReactive() ||
457 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
460 bbtkDebugMessage("change",2,
463 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
465 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
467 // Have to propagate the modification to aval boxes
468 OutputConnectorMapType::iterator i;
469 for (i = bbGetOutputConnectorMap().begin();
470 i != bbGetOutputConnectorMap().end();
473 i->second->SetChangeTime(t);
475 // update the MinOutputChangeTime
476 mMinOutputChangeTime.Set(t);
481 //=========================================================================
483 //=========================================================================
484 /// Sets the ChangeTime of output
485 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
488 bbtkDebugMessage("change",1,
489 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
490 <<bbGetFullName()<<"]"<<std::endl);
494 // c->GetChangeTime() = t;
495 // bbUpdateMinOutputChangeTime(t);
499 //=========================================================================
503 //=========================================================================
504 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
508 if ( t > mMaxInputChangeTime )
510 mMaxInputChangeTime = t;
511 if ( mMinOutputChangeTime > mMaxInputChangeTime )
518 //=========================================================================
520 //=========================================================================
521 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
523 ChangeTime old = mMinOutputChangeTime;
524 mMinOutputChangeTime = MAXLONG;
525 OutputConnectorMapType::iterator i;
526 for (i = bbGetOutputConnectorMap.begin();
527 i != bbGetOutputConnectorMap.end();
530 if (i->second->GetChangeTime() < mMinOutputChangeTime)
531 mMinOutputChangeTime = i->second->GetChangeTime();
533 if ( mMinOutputChangeTime < old )
538 //=========================================================================
541 //=========================================================================
542 /// Signals that the BlackBox has been modified through
543 /// the input connector c
544 /// and propagates it downward
545 /// ** NOT USER INTENDED **
546 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
549 bbtkDebugMessageInc("change",5,
550 "=> BlackBox::bbSetStatusAndPropagate(input,"
551 <<GetIOStatusString(s)<<") ["
552 <<bbGetFullName()<<"]"<<std::endl);
554 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
559 if (bbGetBoxProcessModeValue() == Flash)
565 OutputConnectorMapType::const_iterator o;
566 for ( o = bbGetOutputConnectorMap().begin();
567 o != bbGetOutputConnectorMap().end(); ++o )
569 if (o->second->GetStatus()==UPTODATE)
571 o->second->SetStatus(OUTOFDATE);
572 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
576 if ( ( bbBoxProcessModeIsReactive() ||
577 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
580 bbtkDebugMessage("change",2,
581 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
582 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
584 bbtkDebugMessageInc("change",5,
585 "<= BlackBox::bbSetStatusAndPropagate(input) ["
586 <<bbGetFullName()<<"]"<<std::endl);
588 //=========================================================================
591 //=========================================================================
592 void BlackBox::bbSignalOutputModification(bool reaction)
594 bbtkDebugMessageInc("change",5,
595 "=> BlackBox::bbSignalOutputModification("
597 <<bbGetFullName()<<"]"<<std::endl);
599 OutputConnectorMapType::iterator i;
600 for ( i = bbGetOutputConnectorMap().begin();
601 i != bbGetOutputConnectorMap().end(); ++i)
603 // std::cout << "Stat = "
604 //<<GetIOStatusString(i->second->GetStatus())
606 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
607 // See bbtkSampleOutputObserver
608 // if (i->second->GetStatus()==UPTODATE)
610 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
614 if (reaction) bbGlobalProcessExecutionList();
616 bbtkDebugMessageDec("change",5,
617 "<= BlackBox::bbSignalOutputModification() ["
618 <<bbGetFullName()<<"]"<<std::endl);
621 //=========================================================================
622 //=========================================================================
623 void BlackBox::bbSignalOutputModification(const std::string& output,
626 bbtkDebugMessageInc("change",5,
627 "=> BlackBox::bbSignalOutputModification("
628 <<output<<","<<reaction<<") ["
629 <<bbGetFullName()<<"]"<<std::endl);
631 OutputConnectorMapType::iterator i =
632 bbGetOutputConnectorMap().find(output);
635 if ( i == bbGetOutputConnectorMap().end() )
637 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
640 // if (i->second->GetStatus()==UPTODATE)
642 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
643 // Has to notify the output "BoxChange" also
644 if (output != "BoxChange")
646 i = bbGetOutputConnectorMap().find("BoxChange");
647 if ( i != bbGetOutputConnectorMap().end() )
649 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
652 if (reaction) bbGlobalProcessExecutionList();
655 bbtkDebugMessageDec("change",5,
656 "<= BlackBox::bbSignalOutputModification("
658 <<bbGetFullName()<<"]"<<std::endl);
661 //=========================================================================
662 //=========================================================================
663 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
666 bbtkDebugMessageInc("change",5,
667 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
668 <<bbGetFullName()<<"]"<<std::endl);
669 OutputConnectorMapType::iterator i;
670 std::vector<std::string>::const_iterator o;
671 bool changed = false;
672 for (o=output.begin();o!=output.end();++o)
674 // the output "BoxChange" must be signaled **AFTER** all others
675 if (*o == "BoxChange") continue;
676 // Look for the connector
677 i = bbGetOutputConnectorMap().find(*o);
678 if ( i == bbGetOutputConnectorMap().end() )
680 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
683 // if (i->second->GetStatus()==UPTODATE)
685 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
689 // Has to notify the output "BoxChange" also
690 i = bbGetOutputConnectorMap().find("BoxChange");
691 if ( changed && (i != bbGetOutputConnectorMap().end()))
693 // if (i->second->GetStatus()==UPTODATE)
695 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
696 if (reaction) bbGlobalProcessExecutionList();
700 bbtkDebugMessageDec("change",5,
701 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
702 <<bbGetFullName()<<"]"<<std::endl);
705 //=========================================================================
713 //=========================================================================
714 /// Main processing method of the box.
715 void BlackBox::bbExecute(bool force)
717 bbtkDebugMessageInc("process",2,
718 "=> BlackBox::bbExecute("<<(int)force<<") ["
719 <<bbGetFullName()<<"]"<<std::endl);
721 // If already executing : return
723 if (bbGetExecuting())
725 bbtkDebugMessage("process",2,
726 " -> already executing : abort"<<std::endl);
731 // If execution frozen : return
732 if (bbGlobalGetFreezeExecution())
734 bbtkDebugMessage("process",2,
735 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
740 // If force is true then update is triggered even if the box is UPTODATE
741 // if (force) bbSetModifiedStatus();
743 // Calls the main recursive execution method
744 bbRecursiveExecute(Connection::Pointer());
746 bbtkDebugMessageDec("process",2,
747 "<= BlackBox::bbExecute() ["
748 <<bbGetFullName()<<"]"<<std::endl);
750 //=========================================================================
753 //=========================================================================
754 /// Main recursive processing method of the box.
755 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
757 bbtkDebugMessageInc("process",3,
758 "=> BlackBox::bbRecursiveExecute("
759 <<(caller?caller->GetFullName():"0")<<") ["
760 <<bbGetFullName()<<"]"<<std::endl);
762 // If already executing : return
763 if (bbGetExecuting())
765 bbtkDebugMessage("process",3,
766 " -> already executing : abort"<<std::endl);
770 bbSetExecuting(true);
771 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
772 bbGlobalSetSomeBoxExecuting(true);
774 this->bbCreateWidget();
776 // Updates its inputs
777 IOStatus s = bbUpdateInputs();
779 if ( (s != UPTODATE) ||
780 bbBoxProcessModeIsAlways() )
782 // Displays the window (WxBlackbox)
783 // bbShowWindow(caller);
785 // Actual processing (virtual)
789 // Update the I/O statuses
790 bbComputePostProcessStatus();
794 // Test output status...
795 OutputConnectorMapType::iterator o;
796 for ( o = bbGetOutputConnectorMap().begin();
797 o!= bbGetOutputConnectorMap().end(); ++o)
799 if (o->second->GetStatus() != UPTODATE)
801 bbtkWarning("BlackBox::bbRecursiveExecute ["
803 <<"] : all inputs are Up-to-date but output '"
804 <<o->first<<"' is Out-of-date ???");
808 bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
812 this->bbShowWidget();
815 bbtkDebugMessage("process",3,
816 "<= BlackBox::bbRecursiveExecute() ["
817 <<bbGetFullName()<<"]"<<std::endl);
819 bbSetExecuting(false);
820 bbGlobalSetSomeBoxExecuting(wasExecuting);
825 //=========================================================================
831 //=========================================================================
832 /// Updates the BlackBox inputs
833 /// Calls RecursiveExecute on all BlackBoxInputConnector
834 /// \returns The maximum of final IOStatus after each input update
835 IOStatus BlackBox::bbUpdateInputs()
837 bbtkDebugMessageInc("process",4,
838 "=> BlackBox::bbUpdateInputs() ["
839 <<bbGetFullName()<<"]"
842 IOStatus s = UPTODATE;
844 InputConnectorMapType::iterator i;
845 for ( i = bbGetInputConnectorMap().begin();
846 i!= bbGetInputConnectorMap().end(); ++i)
848 // if (i->first=="WinHide") continue;
849 // If input type is Void : no recurse
850 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
853 bbtkDebugMessageDec("change",2,
854 bbGetName()<<"."<<i->first
855 <<" ["<<i->second<<"] "
856 <<" status before update = '"
857 <<GetIOStatusString(i->second->GetStatus())
859 i->second->RecursiveExecute();
860 IOStatus t = i->second->GetStatus();
862 bbtkDebugMessageDec("change",2,
863 bbGetName()<<"."<<i->first
864 <<" ["<<i->second<<"] "
865 <<" status before process = '"
866 <<GetIOStatusString(i->second->GetStatus())
870 bbtkDebugMessageDec("process",4,
871 "<= BlackBox::bbUpdateInputs() ["
872 <<bbGetFullName()<<"]"
878 //=========================================================================
880 //==================================================================
881 /// Computes the final IOStatus of inputs and outputs after processing
882 void BlackBox::bbComputePostProcessStatus()
884 bbtkDebugMessageInc("process",4,
885 "=> BlackBox::bbComputePostProcessStatus() ["
886 <<bbGetFullName()<<"]"
889 IOStatus new_output_status = UPTODATE;
890 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
892 // Update the input statuses
893 InputConnectorMapType::iterator i;
894 for ( i = bbGetInputConnectorMap().begin();
895 i!= bbGetInputConnectorMap().end(); ++i)
897 IOStatus t = i->second->GetStatus();
898 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
899 // A previously MODIFIED status turns to UPTODATE
900 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
901 bbtkDebugMessage("change",2,
902 bbGetName()<<"."<<i->first<<" : "
903 << GetIOStatusString(t) << " -> "
904 << GetIOStatusString(i->second->GetStatus())
907 bbtkDebugMessage("change",2,
908 bbGetName()<<" new output status : "
909 << GetIOStatusString(new_output_status)
911 // Update the output statuses
912 OutputConnectorMapType::iterator o;
913 for ( o = bbGetOutputConnectorMap().begin();
914 o!= bbGetOutputConnectorMap().end(); ++o)
916 o->second->SetStatus(new_output_status);
919 bbtkDebugMessageInc("process",4,
920 "<= BlackBox::bbComputePostProcessStatus() ["
921 <<bbGetFullName()<<"]"
925 //==================================================================
927 //=========================================================================
928 /// Connects the input <name> to the connection c
929 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
931 bbtkDebugMessage("connection",2,
932 "==> BlackBox::bbConnectInput(\""
933 <<name<<"\","<<c->GetFullName()<<") ["
934 <<bbGetFullName()<<"]"
938 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
939 if (i==bbGetInputConnectorMap().end())
941 bbtkError("no input called '"<<name<<"'");
943 i->second->SetConnection(c);
944 // The input *MUST* be set OUTOFDATE to update its input on next execution
945 bbSetStatusAndPropagate(i->second,OUTOFDATE);
947 bbtkDebugMessage("connection",2,
948 "<== BlackBox::bbConnectInput(\""
949 <<name<<"\","<<c->GetFullName()<<") ["
950 <<bbGetFullName()<<"]"
954 //=========================================================================
957 //=========================================================================
958 /// Connects the output <name> to the connection c
959 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
961 bbtkDebugMessage("connection",2,
962 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
963 <<c->GetFullName()<<") ["
964 <<bbGetFullName()<<"]"<<std::endl);
966 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
967 if (i==bbGetOutputConnectorMap().end())
969 bbtkError("no output called '"<<name<<"'");
971 i->second->SetConnection(c);
973 bbtkDebugMessage("connection",2,
974 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
975 <<c->GetFullName()<<") ["
976 <<bbGetFullName()<<"]"<<std::endl);
979 //=========================================================================
982 //=========================================================================
983 /// Disconnects the input <name> from the connection c
984 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
987 bbtkDebugMessage("connection",2,
988 "==> BlackBox::bbDisconnectInput(\""<<name
989 <<"\","<<c->GetFullName()<<") ["
990 <<bbGetFullName()<<"]"
996 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1000 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
1001 if (i==bbGetInputConnectorMap().end())
1003 bbtkError("no input called '"<<name<<"'");
1005 i->second->UnsetConnection(c);
1007 bbtkDebugMessage("connection",2,
1008 "<== BlackBox::bbDisconnectInput(\""<<name
1009 <<"\","<<c->GetFullName()<<") ["
1010 <<bbGetFullName()<<"]"
1014 //=========================================================================
1017 //=========================================================================
1018 /// Disconnects the output <name> from the connection c
1019 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
1021 bbtkDebugMessage("connection",2,
1022 "==> BlackBox::bbDisconnectOutput(\""<<name
1023 <<"\","<<c->GetFullName()<<") ["
1024 <<bbGetFullName()<<"]"
1029 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1033 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1034 if (i==bbGetOutputConnectorMap().end())
1036 bbtkError("no output called '"<<name<<"'");
1038 i->second->UnsetConnection(c);
1040 bbtkDebugMessage("connection",2,
1041 "<== BlackBox::bbDisconnectOutput(\""<<name
1042 <<"\","<<c->GetFullName()<<") ["
1043 <<bbGetFullName()<<"]"
1046 //=========================================================================
1049 //=========================================================================
1051 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1053 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1055 //=========================================================================
1058 //=========================================================================
1059 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1062 // Looks for the adaptor
1063 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1066 Package::Pointer p = bbGetDescriptor()->GetPackage();
1067 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1069 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1070 BlackBox::Pointer a;
1074 bbGetOutputType(output),
1075 typeid(std::string),
1077 } catch (bbtk::Exception e)
1082 a->bbSetInput("In",bbGetOutput(output));
1084 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1086 v="? (no adaptor found)";
1091 v="? (no factory found)";
1097 v = bbGetOutput(output).unsafe_get<std::string>() ;
1101 //=========================================================================
1103 //=========================================================================
1104 std::string BlackBox::bbGetInputAsString( const std::string &input )
1107 // Looks for the adaptor
1108 if (bbGetInputType(input) != typeid(std::string))
1111 Package::Pointer p = bbGetDescriptor()->GetPackage();
1112 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1114 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1115 BlackBox::Pointer a;
1119 bbGetInputType(input),
1120 typeid(std::string),
1122 }catch (bbtk::Exception e)
1128 a->bbSetInput("In",bbGetInput(input));
1130 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1134 v="? (no adaptor found)";
1139 v="? (no factory found)";
1144 v = bbGetInput(input).unsafe_get<std::string>() ;
1148 //=======================================================================
1150 //=======================================================================
1151 // Replaces substrings "<" by "["
1152 void SubsBrackets ( std::string& s )
1154 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1155 std::string ss("<");
1156 std::string::size_type pos = 0;
1158 std::string cr("[");
1159 while ( pos != std::string::npos )
1161 // std::cout << "*** find one "<<std::endl;
1162 s.replace(pos,1,cr.c_str(),1);
1163 pos = s.find(ss, pos);
1169 while ( pos != std::string::npos )
1171 // std::cout << "*** find one "<<std::endl;
1172 s.replace(pos,1,cr.c_str(),1);
1173 pos = s.find(ss, pos);
1179 while ( pos != std::string::npos )
1181 // std::cout << "*** find one "<<std::endl;
1182 s.replace(pos,1,cr.c_str(),1);
1183 pos = s.find(ss, pos);
1184 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1186 //=======================================================================
1188 //=========================================================================
1189 /// Write Graphviz-dot description in file
1190 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1191 BlackBox::Pointer parentblackbox,
1192 int detail, int level,
1193 bool instanceOrtype,
1194 bool relative_link )
1197 InputConnectorMapType::iterator i;
1199 std::string labelStr;
1200 std::string valueStr("");
1203 labelStr = bbGetName() ;
1205 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1207 labelStr = bbGetName();
1208 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1211 SubsBrackets(labelStr);
1214 labelStr = labelStr + " | {{ ";
1215 std::string tempStrTypeName;
1218 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1222 labelStr=labelStr+" | ";
1225 if (instanceOrtype==true)
1227 valueStr = this->bbGetInputAsString(i->first) + " = ";
1229 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1230 tempStrTypeName=id->GetTypeName();
1231 SubsBrackets(tempStrTypeName);
1232 std::string Name(i->first);
1234 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1236 labelStr=labelStr+ " } | {";
1238 OutputConnectorMapType::iterator ii;
1239 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1243 labelStr=labelStr+" | ";
1246 if (instanceOrtype==true)
1248 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1250 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1251 tempStrTypeName=id->GetTypeName();
1252 SubsBrackets(tempStrTypeName);
1253 std::string Name(ii->first);
1255 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1257 labelStr = labelStr+ " } }" ;
1261 bbWriteDotInputOutputName(ff,true,detail,level);
1262 std::string tmp ( bbGetTypeName() );
1266 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1268 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1270 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1271 // std::cout << labelStr << std::endl;
1274 if (GetThisPointer<BlackBox>()!=parentblackbox){
1275 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1279 Connection* con = i->second->GetConnection();
1281 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1282 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1284 a->bbWriteDotInputOutputName(ff,false,detail,level);
1287 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1290 b->bbWriteDotInputOutputName(ff,true,detail,level);
1293 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1295 fprintf(ff,"%s\n",";");
1299 } // if parentblackbox
1301 //=========================================================================
1306 //=========================================================================
1307 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1308 int detail, int level
1309 /*,Factory *factory*/ )
1312 if (this->bbGetDescriptor()->GetPackage())
1314 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1315 this->bbGetDescriptor()->GetPackage()->GetName()
1316 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1320 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1325 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1326 <<mMinOutputChangeTime<<"]"<<std::endl);
1330 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1331 <<mMinOutputChangeTime<<"]"<<std::endl);
1334 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1335 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1337 std::vector<std::string> iname;
1338 std::vector<std::string> ivalue;
1339 std::vector<std::string> iconn;
1340 std::vector<std::string> istatus;
1342 InputConnectorMapType::iterator i;
1343 unsigned int namelmax = 0;
1344 unsigned int valuelmax = 0;
1345 // unsigned int connlmax = 0;
1346 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1348 iname.push_back(i->first);
1349 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1350 ivalue.push_back(bbGetInputAsString(i->first));
1351 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1353 Connection* con = i->second->GetConnection();
1355 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1357 s += con->GetOriginalBlackBoxFromOutput();
1360 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1362 OutputConnectorMapType::iterator o;
1363 std::vector<std::string> oname;
1364 std::vector<std::string> ovalue;
1365 std::vector<std::vector<std::string> > oconn;
1366 std::vector<std::string> ostatus;
1367 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1369 oname.push_back(o->first);
1370 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1371 ovalue.push_back(bbGetOutputAsString(o->first));
1372 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1373 std::vector<std::string> ss;
1374 const std::vector<Connection*>& con
1375 = o->second->GetConnectionVector();
1376 std::vector<Connection*>::const_iterator c;
1377 for (c=con.begin();c!=con.end();++c)
1380 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1382 s += (*c)->GetOriginalBlackBoxToInput();
1385 oconn.push_back(ss);
1386 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1390 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1392 bbtkMessage("Help",1," * No inputs"<<std::endl);
1394 std::vector<std::string>::iterator i1,i2,i3,i4;
1395 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1396 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1397 ++i1,++i2,++i3,++i4)
1399 std::string name(*i1);
1401 name.append(1+namelmax-name.size(),' ');
1402 std::string value(*i2);
1404 value.append(1+valuelmax-value.size(),' ');
1406 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1409 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1410 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1414 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1416 bbtkMessage("Help",1," * No outputs"<<std::endl);
1418 std::vector<std::vector<std::string> >::iterator i5;
1420 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1421 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1422 ++i1,++i2,++i4,++i5)
1424 std::string name(*i1);
1426 name.append(1+namelmax-name.size(),' ');
1427 std::string value(*i2);
1429 value.append(1+valuelmax-value.size(),' ');
1431 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1434 std::string pref = " '"+name+" = '"+value;
1435 for (i3=i5->begin();i3!=i5->end();++i3)
1437 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1438 pref.replace(0,pref.size(),pref.size(),' ');
1441 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1445 //=========================================================================
1447 static bool bbmgGlobalProcessingExecutionList = false;
1449 //=========================================================================
1450 void BlackBox::bbGlobalProcessExecutionList()
1452 bbtkDebugMessageInc("process",3,
1453 "=> BlackBox::bbGlobalProcessExecutionList()"
1455 if (bbmgGlobalProcessingExecutionList)
1457 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1460 bbmgGlobalProcessingExecutionList = true;
1462 std::set<BlackBox::WeakPointer>::iterator i;
1463 while (bbmgExecutionList.size()>0)
1465 i = bbmgExecutionList.begin();
1466 BlackBox::WeakPointer p = *i;
1467 bbmgExecutionList.erase(i);
1470 bbtkDebugMessage("process",4,
1472 p.lock()->bbGetFullName()<<std::endl);
1473 p.lock()->bbExecute(true);
1477 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1481 bbmgExecutionList.clear();
1482 bbtkDebugMessageDec("process",3,
1483 "<= BlackBox::bbGlobalProcessExecutionList()"
1486 bbmgGlobalProcessingExecutionList = false;
1489 //=========================================================================
1491 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1493 return bbmgSomeBoxExecuting;
1496 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1498 bbmgSomeBoxExecuting = b;
1501 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1503 bbmgFreezeExecution = b;
1506 bool BlackBox::bbGlobalGetFreezeExecution()
1508 return bbmgFreezeExecution;
1511 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1513 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1514 if (bbmgGlobalProcessingExecutionList)
1516 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1518 bbmgExecutionList.insert(b);
1522 //=========================================================================
1524 //=========================================================================
1525 void BlackBox::Check(bool recursive)
1527 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1528 <<"] ... OK"<<std::endl);
1530 //=========================================================================
1532 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1534 bbtk::BlackBoxInputConnector *cc;
1535 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1536 if (cc->GetConnection()!=NULL)
1538 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1544 } // EO namespace bbtk