1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/03/23 13:06:41 $
6 Version: $Revision: 1.40 $
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;
386 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
387 <<"' unknown. Possible values : "
388 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
389 <<"'1'/'A'/'a'/'Always'/'always' | "
390 <<"'2'/'R'/'r'/'Reactive'/'reactive'"<<std::endl);
392 //=========================================================================
394 //=========================================================================
395 bool BlackBox::bbBoxProcessModeIsReactive() const
397 return (bbGetBoxProcessModeValue() == Reactive);
399 //=========================================================================
401 //=========================================================================
402 bool BlackBox::bbBoxProcessModeIsAlways() const
404 return (bbGetBoxProcessModeValue() == Always);
406 //=========================================================================
411 //=========================================================================
412 void BlackBox::bbAddOutputObserver(const std::string& output,
413 OutputChangeCallbackType f)
415 bbGetOutputConnector(output).AddChangeObserver(f);
417 //=========================================================================
419 //=========================================================================
420 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
421 OutputChangeCallbackType f)
423 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
425 //=========================================================================
429 //=========================================================================
430 /// Sets the ChangeTime of input
431 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
434 bbtkDebugMessage("change",1,
435 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
436 <<bbGetFullName()<<"]"<<std::endl);
438 // If new time is greater than old one
439 if ( c->SetChangeTime(t) )
441 bool was_up_to_date = bbIsUpToDate();
442 // If new time is greater than the old max time of inputs
443 if ( mMaxInputChangeTime.Set(t) )
445 // If the box turned out-of-date
446 if ( was_up_to_date && bbIsOutOfDate() )
449 if ( ( bbBoxProcessModeIsReactive() ||
450 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
453 bbtkDebugMessage("change",2,
456 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
458 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
460 // Have to propagate the modification to aval boxes
461 OutputConnectorMapType::iterator i;
462 for (i = bbGetOutputConnectorMap().begin();
463 i != bbGetOutputConnectorMap().end();
466 i->second->SetChangeTime(t);
468 // update the MinOutputChangeTime
469 mMinOutputChangeTime.Set(t);
474 //=========================================================================
476 //=========================================================================
477 /// Sets the ChangeTime of output
478 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
481 bbtkDebugMessage("change",1,
482 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
483 <<bbGetFullName()<<"]"<<std::endl);
487 // c->GetChangeTime() = t;
488 // bbUpdateMinOutputChangeTime(t);
492 //=========================================================================
496 //=========================================================================
497 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
501 if ( t > mMaxInputChangeTime )
503 mMaxInputChangeTime = t;
504 if ( mMinOutputChangeTime > mMaxInputChangeTime )
511 //=========================================================================
513 //=========================================================================
514 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
516 ChangeTime old = mMinOutputChangeTime;
517 mMinOutputChangeTime = MAXLONG;
518 OutputConnectorMapType::iterator i;
519 for (i = bbGetOutputConnectorMap.begin();
520 i != bbGetOutputConnectorMap.end();
523 if (i->second->GetChangeTime() < mMinOutputChangeTime)
524 mMinOutputChangeTime = i->second->GetChangeTime();
526 if ( mMinOutputChangeTime < old )
531 //=========================================================================
534 //=========================================================================
535 /// Signals that the BlackBox has been modified through
536 /// the input connector c
537 /// and propagates it downward
538 /// ** NOT USER INTENDED **
539 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
542 bbtkDebugMessageInc("change",5,
543 "=> BlackBox::bbSetStatusAndPropagate(input,"
544 <<GetIOStatusString(s)<<") ["
545 <<bbGetFullName()<<"]"<<std::endl);
547 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
549 OutputConnectorMapType::const_iterator o;
550 for ( o = bbGetOutputConnectorMap().begin();
551 o != bbGetOutputConnectorMap().end(); ++o )
553 if (o->second->GetStatus()==UPTODATE)
555 o->second->SetStatus(OUTOFDATE);
556 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
560 if ( ( bbBoxProcessModeIsReactive() ||
561 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
564 bbtkDebugMessage("change",2,
565 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
566 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
568 bbtkDebugMessageInc("change",5,
569 "<= BlackBox::bbSetStatusAndPropagate(input) ["
570 <<bbGetFullName()<<"]"<<std::endl);
572 //=========================================================================
575 //=========================================================================
576 void BlackBox::bbSignalOutputModification(bool reaction)
578 bbtkDebugMessageInc("change",5,
579 "=> BlackBox::bbSignalOutputModification("
581 <<bbGetFullName()<<"]"<<std::endl);
583 OutputConnectorMapType::iterator i;
584 for ( i = bbGetOutputConnectorMap().begin();
585 i != bbGetOutputConnectorMap().end(); ++i)
587 // std::cout << "Stat = "
588 //<<GetIOStatusString(i->second->GetStatus())
590 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
591 // See bbtkSampleOutputObserver
592 // if (i->second->GetStatus()==UPTODATE)
594 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
598 if (reaction) bbGlobalProcessExecutionList();
600 bbtkDebugMessageDec("change",5,
601 "<= BlackBox::bbSignalOutputModification() ["
602 <<bbGetFullName()<<"]"<<std::endl);
605 //=========================================================================
606 //=========================================================================
607 void BlackBox::bbSignalOutputModification(const std::string& output,
610 bbtkDebugMessageInc("change",5,
611 "=> BlackBox::bbSignalOutputModification("
612 <<output<<","<<reaction<<") ["
613 <<bbGetFullName()<<"]"<<std::endl);
615 OutputConnectorMapType::iterator i =
616 bbGetOutputConnectorMap().find(output);
619 if ( i == bbGetOutputConnectorMap().end() )
621 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
624 // if (i->second->GetStatus()==UPTODATE)
626 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
627 // Has to notify the output "BoxChange" also
628 if (output != "BoxChange")
630 i = bbGetOutputConnectorMap().find("BoxChange");
631 if ( i != bbGetOutputConnectorMap().end() )
633 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
636 if (reaction) bbGlobalProcessExecutionList();
639 bbtkDebugMessageDec("change",5,
640 "<= BlackBox::bbSignalOutputModification("
642 <<bbGetFullName()<<"]"<<std::endl);
645 //=========================================================================
646 //=========================================================================
647 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
650 bbtkDebugMessageInc("change",5,
651 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
652 <<bbGetFullName()<<"]"<<std::endl);
653 OutputConnectorMapType::iterator i;
654 std::vector<std::string>::const_iterator o;
655 bool changed = false;
656 for (o=output.begin();o!=output.end();++o)
658 // the output "BoxChange" must be signaled **AFTER** all others
659 if (*o == "BoxChange") continue;
660 // Look for the connector
661 i = bbGetOutputConnectorMap().find(*o);
662 if ( i == bbGetOutputConnectorMap().end() )
664 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
667 // if (i->second->GetStatus()==UPTODATE)
669 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
673 // Has to notify the output "BoxChange" also
674 i = bbGetOutputConnectorMap().find("BoxChange");
675 if ( changed && (i != bbGetOutputConnectorMap().end()))
677 // if (i->second->GetStatus()==UPTODATE)
679 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
680 if (reaction) bbGlobalProcessExecutionList();
684 bbtkDebugMessageDec("change",5,
685 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
686 <<bbGetFullName()<<"]"<<std::endl);
689 //=========================================================================
697 //=========================================================================
698 /// Main processing method of the box.
699 void BlackBox::bbExecute(bool force)
701 bbtkDebugMessageInc("process",2,
702 "=> BlackBox::bbExecute("<<(int)force<<") ["
703 <<bbGetFullName()<<"]"<<std::endl);
705 // If already executing : return
707 if (bbGetExecuting())
709 bbtkDebugMessage("process",2,
710 " -> already executing : abort"<<std::endl);
715 // If execution frozen : return
716 if (bbGlobalGetFreezeExecution())
718 bbtkDebugMessage("process",2,
719 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
724 // If force is true then update is triggered even if the box is UPTODATE
725 // if (force) bbSetModifiedStatus();
727 // Calls the main recursive execution method
728 bbRecursiveExecute(Connection::Pointer());
730 bbtkDebugMessageDec("process",2,
731 "<= BlackBox::bbExecute() ["
732 <<bbGetFullName()<<"]"<<std::endl);
734 //=========================================================================
737 //=========================================================================
738 /// Main recursive processing method of the box.
739 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
741 bbtkDebugMessageInc("process",3,
742 "=> BlackBox::bbRecursiveExecute("
743 <<(caller?caller->GetFullName():"0")<<") ["
744 <<bbGetFullName()<<"]"<<std::endl);
746 // If already executing : return
747 if (bbGetExecuting())
749 bbtkDebugMessage("process",3,
750 " -> already executing : abort"<<std::endl);
754 bbSetExecuting(true);
755 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
756 bbGlobalSetSomeBoxExecuting(true);
758 this->bbCreateWidget();
760 // Updates its inputs
761 IOStatus s = bbUpdateInputs();
763 if ( (s != UPTODATE) ||
764 bbBoxProcessModeIsAlways() )
766 // Displays the window (WxBlackbox)
767 // bbShowWindow(caller);
769 // Actual processing (virtual)
773 // Update the I/O statuses
774 bbComputePostProcessStatus();
778 // Test output status...
779 OutputConnectorMapType::iterator o;
780 for ( o = bbGetOutputConnectorMap().begin();
781 o!= bbGetOutputConnectorMap().end(); ++o)
783 if (o->second->GetStatus() != UPTODATE)
785 bbtkWarning("BlackBox::bbRecursiveExecute ["
787 <<"] : all inputs are Up-to-date but output '"
788 <<o->first<<"' is Out-of-date ???");
792 bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
796 this->bbShowWidget();
799 bbtkDebugMessage("process",3,
800 "<= BlackBox::bbRecursiveExecute() ["
801 <<bbGetFullName()<<"]"<<std::endl);
803 bbSetExecuting(false);
804 bbGlobalSetSomeBoxExecuting(wasExecuting);
809 //=========================================================================
815 //=========================================================================
816 /// Updates the BlackBox inputs
817 /// Calls RecursiveExecute on all BlackBoxInputConnector
818 /// \returns The maximum of final IOStatus after each input update
819 IOStatus BlackBox::bbUpdateInputs()
821 bbtkDebugMessageInc("process",4,
822 "=> BlackBox::bbUpdateInputs() ["
823 <<bbGetFullName()<<"]"
826 IOStatus s = UPTODATE;
828 InputConnectorMapType::iterator i;
829 for ( i = bbGetInputConnectorMap().begin();
830 i!= bbGetInputConnectorMap().end(); ++i)
832 // if (i->first=="WinHide") continue;
833 // If input type is Void : no recurse
834 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
837 bbtkDebugMessageDec("change",2,
838 bbGetName()<<"."<<i->first
839 <<" ["<<i->second<<"] "
840 <<" status before update = '"
841 <<GetIOStatusString(i->second->GetStatus())
843 i->second->RecursiveExecute();
844 IOStatus t = i->second->GetStatus();
846 bbtkDebugMessageDec("change",2,
847 bbGetName()<<"."<<i->first
848 <<" ["<<i->second<<"] "
849 <<" status before process = '"
850 <<GetIOStatusString(i->second->GetStatus())
854 bbtkDebugMessageDec("process",4,
855 "<= BlackBox::bbUpdateInputs() ["
856 <<bbGetFullName()<<"]"
862 //=========================================================================
864 //==================================================================
865 /// Computes the final IOStatus of inputs and outputs after processing
866 void BlackBox::bbComputePostProcessStatus()
868 bbtkDebugMessageInc("process",4,
869 "=> BlackBox::bbComputePostProcessStatus() ["
870 <<bbGetFullName()<<"]"
873 IOStatus new_output_status = UPTODATE;
874 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
876 // Update the input statuses
877 InputConnectorMapType::iterator i;
878 for ( i = bbGetInputConnectorMap().begin();
879 i!= bbGetInputConnectorMap().end(); ++i)
881 IOStatus t = i->second->GetStatus();
882 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
883 // A previously MODIFIED status turns to UPTODATE
884 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
885 bbtkDebugMessage("change",2,
886 bbGetName()<<"."<<i->first<<" : "
887 << GetIOStatusString(t) << " -> "
888 << GetIOStatusString(i->second->GetStatus())
891 bbtkDebugMessage("change",2,
892 bbGetName()<<" new output status : "
893 << GetIOStatusString(new_output_status)
895 // Update the output statuses
896 OutputConnectorMapType::iterator o;
897 for ( o = bbGetOutputConnectorMap().begin();
898 o!= bbGetOutputConnectorMap().end(); ++o)
900 o->second->SetStatus(new_output_status);
903 bbtkDebugMessageInc("process",4,
904 "<= BlackBox::bbComputePostProcessStatus() ["
905 <<bbGetFullName()<<"]"
909 //==================================================================
911 //=========================================================================
912 /// Connects the input <name> to the connection c
913 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
915 bbtkDebugMessage("connection",2,
916 "==> BlackBox::bbConnectInput(\""
917 <<name<<"\","<<c->GetFullName()<<") ["
918 <<bbGetFullName()<<"]"
922 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
923 if (i==bbGetInputConnectorMap().end())
925 bbtkError("no input called '"<<name<<"'");
927 i->second->SetConnection(c);
928 // The input *MUST* be set OUTOFDATE to update its input on next execution
929 bbSetStatusAndPropagate(i->second,OUTOFDATE);
931 bbtkDebugMessage("connection",2,
932 "<== BlackBox::bbConnectInput(\""
933 <<name<<"\","<<c->GetFullName()<<") ["
934 <<bbGetFullName()<<"]"
938 //=========================================================================
941 //=========================================================================
942 /// Connects the output <name> to the connection c
943 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
945 bbtkDebugMessage("connection",2,
946 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
947 <<c->GetFullName()<<") ["
948 <<bbGetFullName()<<"]"<<std::endl);
950 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
951 if (i==bbGetOutputConnectorMap().end())
953 bbtkError("no output called '"<<name<<"'");
955 i->second->SetConnection(c);
957 bbtkDebugMessage("connection",2,
958 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
959 <<c->GetFullName()<<") ["
960 <<bbGetFullName()<<"]"<<std::endl);
963 //=========================================================================
966 //=========================================================================
967 /// Disconnects the input <name> from the connection c
968 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
971 bbtkDebugMessage("connection",2,
972 "==> BlackBox::bbDisconnectInput(\""<<name
973 <<"\","<<c->GetFullName()<<") ["
974 <<bbGetFullName()<<"]"
980 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
984 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
985 if (i==bbGetInputConnectorMap().end())
987 bbtkError("no input called '"<<name<<"'");
989 i->second->UnsetConnection(c);
991 bbtkDebugMessage("connection",2,
992 "<== BlackBox::bbDisconnectInput(\""<<name
993 <<"\","<<c->GetFullName()<<") ["
994 <<bbGetFullName()<<"]"
998 //=========================================================================
1001 //=========================================================================
1002 /// Disconnects the output <name> from the connection c
1003 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
1005 bbtkDebugMessage("connection",2,
1006 "==> BlackBox::bbDisconnectOutput(\""<<name
1007 <<"\","<<c->GetFullName()<<") ["
1008 <<bbGetFullName()<<"]"
1013 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1017 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1018 if (i==bbGetOutputConnectorMap().end())
1020 bbtkError("no output called '"<<name<<"'");
1022 i->second->UnsetConnection(c);
1024 bbtkDebugMessage("connection",2,
1025 "<== BlackBox::bbDisconnectOutput(\""<<name
1026 <<"\","<<c->GetFullName()<<") ["
1027 <<bbGetFullName()<<"]"
1030 //=========================================================================
1033 //=========================================================================
1035 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1037 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1039 //=========================================================================
1042 //=========================================================================
1043 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1046 // Looks for the adaptor
1047 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1050 Package::Pointer p = bbGetDescriptor()->GetPackage();
1051 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1053 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1054 BlackBox::Pointer a;
1058 bbGetOutputType(output),
1059 typeid(std::string),
1061 } catch (bbtk::Exception e)
1066 a->bbSetInput("In",bbGetOutput(output));
1068 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1070 v="? (no adaptor found)";
1075 v="? (no factory found)";
1081 v = bbGetOutput(output).unsafe_get<std::string>() ;
1085 //=========================================================================
1087 //=========================================================================
1088 std::string BlackBox::bbGetInputAsString( const std::string &input )
1091 // Looks for the adaptor
1092 if (bbGetInputType(input) != typeid(std::string))
1095 Package::Pointer p = bbGetDescriptor()->GetPackage();
1096 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1098 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1099 BlackBox::Pointer a;
1103 bbGetInputType(input),
1104 typeid(std::string),
1106 }catch (bbtk::Exception e)
1112 a->bbSetInput("In",bbGetInput(input));
1114 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1118 v="? (no adaptor found)";
1123 v="? (no factory found)";
1128 v = bbGetInput(input).unsafe_get<std::string>() ;
1132 //=======================================================================
1134 //=======================================================================
1135 // Replaces substrings "<" by "["
1136 void SubsBrackets ( std::string& s )
1138 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1139 std::string ss("<");
1140 std::string::size_type pos = 0;
1142 std::string cr("[");
1143 while ( pos != std::string::npos )
1145 // std::cout << "*** find one "<<std::endl;
1146 s.replace(pos,1,cr.c_str(),1);
1147 pos = s.find(ss, pos);
1153 while ( pos != std::string::npos )
1155 // std::cout << "*** find one "<<std::endl;
1156 s.replace(pos,1,cr.c_str(),1);
1157 pos = s.find(ss, pos);
1163 while ( pos != std::string::npos )
1165 // std::cout << "*** find one "<<std::endl;
1166 s.replace(pos,1,cr.c_str(),1);
1167 pos = s.find(ss, pos);
1168 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1170 //=======================================================================
1172 //=========================================================================
1173 /// Write Graphviz-dot description in file
1174 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1175 BlackBox::Pointer parentblackbox,
1176 int detail, int level,
1177 bool instanceOrtype,
1178 bool relative_link )
1181 InputConnectorMapType::iterator i;
1183 std::string labelStr;
1184 std::string valueStr("");
1187 labelStr = bbGetName() ;
1189 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1191 labelStr = bbGetName();
1192 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1195 SubsBrackets(labelStr);
1198 labelStr = labelStr + " | {{ ";
1199 std::string tempStrTypeName;
1202 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1206 labelStr=labelStr+" | ";
1209 if (instanceOrtype==true)
1211 valueStr = this->bbGetInputAsString(i->first) + " = ";
1213 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1214 tempStrTypeName=id->GetTypeName();
1215 SubsBrackets(tempStrTypeName);
1216 std::string Name(i->first);
1218 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1220 labelStr=labelStr+ " } | {";
1222 OutputConnectorMapType::iterator ii;
1223 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1227 labelStr=labelStr+" | ";
1230 if (instanceOrtype==true)
1232 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1234 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1235 tempStrTypeName=id->GetTypeName();
1236 SubsBrackets(tempStrTypeName);
1237 std::string Name(ii->first);
1239 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1241 labelStr = labelStr+ " } }" ;
1245 bbWriteDotInputOutputName(ff,true,detail,level);
1246 std::string tmp ( bbGetTypeName() );
1250 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1252 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1254 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1255 // std::cout << labelStr << std::endl;
1258 if (GetThisPointer<BlackBox>()!=parentblackbox){
1259 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1263 Connection* con = i->second->GetConnection();
1265 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1266 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1268 a->bbWriteDotInputOutputName(ff,false,detail,level);
1271 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1274 b->bbWriteDotInputOutputName(ff,true,detail,level);
1277 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1279 fprintf(ff,"%s\n",";");
1283 } // if parentblackbox
1285 //=========================================================================
1290 //=========================================================================
1291 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1292 int detail, int level
1293 /*,Factory *factory*/ )
1296 if (this->bbGetDescriptor()->GetPackage())
1298 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1299 this->bbGetDescriptor()->GetPackage()->GetName()
1300 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1304 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1309 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1310 <<mMinOutputChangeTime<<"]"<<std::endl);
1314 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1315 <<mMinOutputChangeTime<<"]"<<std::endl);
1318 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1319 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1321 std::vector<std::string> iname;
1322 std::vector<std::string> ivalue;
1323 std::vector<std::string> iconn;
1324 std::vector<std::string> istatus;
1326 InputConnectorMapType::iterator i;
1327 unsigned int namelmax = 0;
1328 unsigned int valuelmax = 0;
1329 // unsigned int connlmax = 0;
1330 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1332 iname.push_back(i->first);
1333 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1334 ivalue.push_back(bbGetInputAsString(i->first));
1335 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1337 Connection* con = i->second->GetConnection();
1339 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1341 s += con->GetOriginalBlackBoxFromOutput();
1344 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1346 OutputConnectorMapType::iterator o;
1347 std::vector<std::string> oname;
1348 std::vector<std::string> ovalue;
1349 std::vector<std::vector<std::string> > oconn;
1350 std::vector<std::string> ostatus;
1351 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1353 oname.push_back(o->first);
1354 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1355 ovalue.push_back(bbGetOutputAsString(o->first));
1356 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1357 std::vector<std::string> ss;
1358 const std::vector<Connection*>& con
1359 = o->second->GetConnectionVector();
1360 std::vector<Connection*>::const_iterator c;
1361 for (c=con.begin();c!=con.end();++c)
1364 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1366 s += (*c)->GetOriginalBlackBoxToInput();
1369 oconn.push_back(ss);
1370 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1374 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1376 bbtkMessage("Help",1," * No inputs"<<std::endl);
1378 std::vector<std::string>::iterator i1,i2,i3,i4;
1379 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1380 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1381 ++i1,++i2,++i3,++i4)
1383 std::string name(*i1);
1385 name.append(1+namelmax-name.size(),' ');
1386 std::string value(*i2);
1388 value.append(1+valuelmax-value.size(),' ');
1390 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1393 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1394 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1398 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1400 bbtkMessage("Help",1," * No outputs"<<std::endl);
1402 std::vector<std::vector<std::string> >::iterator i5;
1404 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1405 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1406 ++i1,++i2,++i4,++i5)
1408 std::string name(*i1);
1410 name.append(1+namelmax-name.size(),' ');
1411 std::string value(*i2);
1413 value.append(1+valuelmax-value.size(),' ');
1415 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1418 std::string pref = " '"+name+" = '"+value;
1419 for (i3=i5->begin();i3!=i5->end();++i3)
1421 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1422 pref.replace(0,pref.size(),pref.size(),' ');
1425 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1429 //=========================================================================
1431 static bool bbmgGlobalProcessingExecutionList = false;
1433 //=========================================================================
1434 void BlackBox::bbGlobalProcessExecutionList()
1436 bbtkDebugMessageInc("process",3,
1437 "=> BlackBox::bbGlobalProcessExecutionList()"
1439 if (bbmgGlobalProcessingExecutionList)
1441 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1444 bbmgGlobalProcessingExecutionList = true;
1446 std::set<BlackBox::WeakPointer>::iterator i;
1447 while (bbmgExecutionList.size()>0)
1449 i = bbmgExecutionList.begin();
1450 BlackBox::WeakPointer p = *i;
1451 bbmgExecutionList.erase(i);
1454 bbtkDebugMessage("process",4,
1456 p.lock()->bbGetFullName()<<std::endl);
1457 p.lock()->bbExecute(true);
1461 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1465 bbmgExecutionList.clear();
1466 bbtkDebugMessageDec("process",3,
1467 "<= BlackBox::bbGlobalProcessExecutionList()"
1470 bbmgGlobalProcessingExecutionList = false;
1473 //=========================================================================
1475 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1477 return bbmgSomeBoxExecuting;
1480 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1482 bbmgSomeBoxExecuting = b;
1485 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1487 bbmgFreezeExecution = b;
1490 bool BlackBox::bbGlobalGetFreezeExecution()
1492 return bbmgFreezeExecution;
1495 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1497 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1498 if (bbmgGlobalProcessingExecutionList)
1500 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1502 bbmgExecutionList.insert(b);
1506 //=========================================================================
1508 //=========================================================================
1509 void BlackBox::Check(bool recursive)
1511 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1512 <<"] ... OK"<<std::endl);
1514 //=========================================================================
1516 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1518 bbtk::BlackBoxInputConnector *cc;
1519 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1520 if (cc->GetConnection()!=NULL)
1522 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1528 } // EO namespace bbtk