1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2008/12/09 11:48:31 $
6 Version: $Revision: 1.33 $
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 //=========================================================================
156 //=========================================================================
157 /// Main processing method of the box.
158 void BlackBox::bbExecute(bool force)
160 bbtkDebugMessageInc("process",2,
161 "=> BlackBox::bbExecute("<<(int)force<<") ["
162 <<bbGetFullName()<<"]"<<std::endl);
164 // If already executing : return
165 if (bbGetExecuting())
167 bbtkDebugMessage("process",2,
168 " -> already executing : bailing out"<<std::endl);
172 // If execution frozen : return
173 if (bbGlobalGetFreezeExecution())
175 bbtkDebugMessage("process",2,
176 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
181 // If force is true then update is triggered even if the box is UPTODATE
182 // if (force) bbSetModifiedStatus();
184 // Calls the main recursive update method
185 bbBackwardUpdate(Connection::Pointer());
187 bbtkDebugMessageDec("process",2,
188 "<= BlackBox::bbExecute() ["
189 <<bbGetFullName()<<"]"<<std::endl);
191 //=========================================================================
193 //=========================================================================
194 std::string BlackBox::bbGetFullName() const
196 return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
198 //=========================================================================
202 //=========================================================================
203 /// Returns the name with the name of the parent prepended if any
204 std::string BlackBox::bbGetNameWithParent() const
206 if (bbmParent.lock())
208 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
215 //=========================================================================
217 //=========================================================================
218 /// Prints the Help on the BlackBox type
219 void BlackBox::bbGetHelp(bool full) const
221 bbGetDescriptor()->GetHelp(full);
223 //=========================================================================
226 //=========================================================================
227 /// Returns true if the UserBlackBox has an input of name name
228 bool BlackBox::bbHasInput(const std::string& name) const
230 bbtkDebugMessageInc("Kernel",8,
231 "BlackBox::bbHasInput(\""
232 <<name<<"\") ["<<bbGetFullName()<<"]"
234 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
235 != bbGetDescriptor()->GetInputDescriptorMap().end());
236 bbtkDebugDecTab("Kernel",8);
239 //=========================================================================
242 //=========================================================================
243 /// Returns true if the UserBlackBox has an output of name name
244 bool BlackBox::bbHasOutput(const std::string& name) const
246 bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
247 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
248 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
249 != bbGetDescriptor()->GetOutputDescriptorMap().end());
250 bbtkDebugDecTab("Kernel",8);
253 //=========================================================================
256 //=========================================================================
257 /// Gets the output type of a given name
258 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
260 bbtkDebugMessageInc("Kernel",8,
261 "BlackBox::bbGetOutputType(\""
262 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
263 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
264 bbtkDebugDecTab("Kernel",8);
267 //=========================================================================
269 //=========================================================================
270 /// Gets the input type of a given name
271 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
273 bbtkDebugMessageInc("Kernel",8,
274 "BlackBox::bbGetInputType(\""
275 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
276 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
277 bbtkDebugDecTab("Kernel",8);
280 //=========================================================================
283 //=========================================================================
284 /// Allocates the i/o connectors of the black box
285 void BlackBox::bbAllocateConnectors()
287 bbtkDebugMessageInc("Kernel",8,
288 "BlackBox::bbAllocateConnectors() ["
289 <<bbGetFullName()<<"]"
291 const BlackBoxDescriptor::InputDescriptorMapType& imap
292 = bbGetDescriptor()->GetInputDescriptorMap();
293 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
294 for ( i = imap.begin(); i != imap.end(); ++i )
296 bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
297 bbGetInputConnectorMap()[i->second->GetName()]
298 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
300 const BlackBoxDescriptor::OutputDescriptorMapType& omap
301 = bbGetDescriptor()->GetOutputDescriptorMap();
302 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
303 for ( o = omap.begin(); o != omap.end(); ++o )
305 bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
306 bbGetOutputConnectorMap()[o->second->GetName()]
307 = new BlackBoxOutputConnector();
309 bbtkDebugDecTab("Kernel",8);
311 //=========================================================================
314 //=========================================================================
315 /// Desallocates the i/o connectors of the black box
316 void BlackBox::bbDesallocateConnectors()
318 bbtkDebugMessageInc("Kernel",8,
319 "BlackBox::bbDesallocateConnectors()"
322 InputConnectorMapType::const_iterator i;
323 for ( i = bbGetInputConnectorMap().begin();
324 i != bbGetInputConnectorMap().end(); ++i )
326 bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
329 OutputConnectorMapType::const_iterator o;
330 for ( o = bbGetOutputConnectorMap().begin();
331 o != bbGetOutputConnectorMap().end(); ++o )
333 bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
337 bbtkDebugDecTab("Kernel",8);
340 //=========================================================================
343 //=========================================================================
344 /// Copies the input / output values from another box
345 void BlackBox::bbCopyIOValues(BlackBox& from)
347 bbtkDebugMessageInc("Kernel",1,
348 "BlackBox::bbCopyIOValues("
349 <<from.bbGetFullName()<<") ["
350 <<bbGetFullName()<<"]"<<std::endl);
351 // copies the input values
352 const BlackBoxDescriptor::InputDescriptorMapType& imap
353 = bbGetDescriptor()->GetInputDescriptorMap();
354 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
355 for ( i = imap.begin(); i != imap.end(); ++i )
357 if (! i->second->GetCopyConstruct() ) continue;
358 std::string input = i->second->GetName();
359 bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
360 this->bbSetInput(input, from.bbGetInput(input) );
362 // copies the output values
363 const BlackBoxDescriptor::OutputDescriptorMapType& omap
364 = bbGetDescriptor()->GetOutputDescriptorMap();
365 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
366 for ( o = omap.begin(); o != omap.end(); ++o )
368 if (! o->second->GetCopyConstruct() ) continue;
369 std::string output = o->second->GetName();
370 bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
371 this->bbSetOutput(output, from.bbGetOutput(output) );
374 bbtkDebugDecTab("Kernel",9);
377 //=========================================================================
381 //=========================================================================
382 bool BlackBox::bbCanReact() const
384 return ( bbGlobalGetSomeBoxExecuting()
385 #ifdef _USE_WXWIDGETS_
386 || Wx::IsSomeWindowAlive()
390 //=========================================================================
394 //=========================================================================
395 /// User overloadable destruction method of a black box
396 void BlackBox::bbUserDelete()
398 bbtkDebugMessage("process",5,
399 "=> BlackBox::bbUserDelete() ["
400 <<bbGetFullName()<<"]"
401 <<" : not overloaded; using standard deletion"
405 //=========================================================================
408 //=========================================================================
409 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
411 const std::string& p = bbmBoxProcessMode;
413 (p == "P") || (p == "p") ||
414 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
416 (p == "A") || (p == "a") ||
417 (p == "Always") || (p == "always") ) return Always;
419 (p == "R") || (p == "r") ||
420 (p == "Reactive") || (p == "reactive") ) return Reactive;
421 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
422 <<"' unknown. Possible values : "
423 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
424 <<"'1'/'A'/'a'/'Always'/'always' | "
425 <<"'2'/'R'/'r'/'Reactive'/'reactive'"<<std::endl);
427 //=========================================================================
429 //=========================================================================
430 bool BlackBox::bbBoxProcessModeIsReactive() const
432 return (bbGetBoxProcessModeValue() == Reactive);
434 //=========================================================================
436 //=========================================================================
437 bool BlackBox::bbBoxProcessModeIsAlways() const
439 return (bbGetBoxProcessModeValue() == Always);
441 //=========================================================================
446 //=========================================================================
447 void BlackBox::AddChangeObserver(const std::string& output_name,
448 OutputChangeCallbackType f)
451 //=========================================================================
453 //=========================================================================
454 void BlackBox::RemoveChangeObserver(const std::string& output_name,
455 OutputChangeCallbackType f)
458 //=========================================================================
462 //=========================================================================
463 /// Sets the ChangeTime of input
464 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
467 bbtkDebugMessage("change",1,
468 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
469 <<bbGetFullName()<<"]"<<std::endl);
471 // If new time is greater than old one
472 if ( c->SetChangeTime(t) )
474 bool was_up_to_date = bbIsUpToDate();
475 // If new time is greater than the old max time of inputs
476 if ( mMaxInputChangeTime.Set(t) )
478 // If the box turned out-of-date
479 if ( was_up_to_date && bbIsOutOfDate() )
482 if ( ( bbBoxProcessModeIsReactive() ||
483 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
486 bbtkDebugMessage("change",2,
489 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
491 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
493 // Have to propagate the modification to aval boxes
494 OutputConnectorMapType::iterator i;
495 for (i = bbGetOutputConnectorMap().begin();
496 i != bbGetOutputConnectorMap().end();
499 i->second->SetChangeTime(t);
501 // update the MinOutputChangeTime
502 mMinOutputChangeTime.Set(t);
507 //=========================================================================
509 //=========================================================================
510 /// Sets the ChangeTime of output
511 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
514 bbtkDebugMessage("change",1,
515 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
516 <<bbGetFullName()<<"]"<<std::endl);
520 // c->GetChangeTime() = t;
521 // bbUpdateMinOutputChangeTime(t);
525 //=========================================================================
529 //=========================================================================
530 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
534 if ( t > mMaxInputChangeTime )
536 mMaxInputChangeTime = t;
537 if ( mMinOutputChangeTime > mMaxInputChangeTime )
544 //=========================================================================
546 //=========================================================================
547 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
549 ChangeTime old = mMinOutputChangeTime;
550 mMinOutputChangeTime = MAXLONG;
551 OutputConnectorMapType::iterator i;
552 for (i = bbGetOutputConnectorMap.begin();
553 i != bbGetOutputConnectorMap.end();
556 if (i->second->GetChangeTime() < mMinOutputChangeTime)
557 mMinOutputChangeTime = i->second->GetChangeTime();
559 if ( mMinOutputChangeTime < old )
564 //=========================================================================
567 //=========================================================================
568 /// Signals that the BlackBox has been modified through
569 /// the input connector c
570 /// and propagates it downward
571 /// ** NOT USER INTENDED **
572 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
575 bbtkDebugMessageInc("change",5,
576 "=> BlackBox::bbSetStatusAndPropagate(input,"
577 <<GetIOStatusString(s)<<") ["
578 <<bbGetFullName()<<"]"<<std::endl);
580 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
582 OutputConnectorMapType::const_iterator o;
583 for ( o = bbGetOutputConnectorMap().begin();
584 o != bbGetOutputConnectorMap().end(); ++o )
586 // bbSetStatusAndPropagate(o->second, OUTOFDATE);
587 if (o->second->GetStatus()==UPTODATE)
589 o->second->SetStatus(OUTOFDATE);
590 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
594 if ( ( bbBoxProcessModeIsReactive() ||
595 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
598 bbtkDebugMessage("change",2,
599 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
600 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
602 bbtkDebugMessageInc("change",5,
603 "<= BlackBox::bbSetStatusAndPropagate(input) ["
604 <<bbGetFullName()<<"]"<<std::endl);
606 //=========================================================================
608 //=========================================================================
609 void BlackBox::bbSetStatusAndPropagate(BlackBoxOutputConnector* c,
612 bbtkError("bbSetStatusAndPropagate(BlackBoxOutputConnector* c,IOStatus s)");
614 if (i->GetStatus()==UPTODATE)
616 i->second->SetStatus(s);
617 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
621 //=========================================================================
624 /// Signals that the BlackBox has been modified
626 void BlackBox::bbSetModifiedStatus(BlackBoxInputConnector* c)
628 bbtkDebugMessage("modified",1,
629 "==> BlackBox::bbSetModifiedStatus("<<c<<") ["
630 <<bbGetFullName()<<"]"<<std::endl);
632 if ( (c==bbGetInputConnectorMap().find("WinHide")->second) )
633 // && (bbCanReact()))
635 bbtkDebugMessage("modified",2,
636 "-> Hide triggered by WinHide input change"
638 this->bbHideWindow();
639 this->bbSetStatus(MODIFIED);
642 if ( (c==bbGetInputConnectorMap().find("WinClose")->second) )
643 // && (bbCanReact()))
645 bbtkDebugMessage("modified",2,
646 "-> Close triggered by WinClose input change"
648 this->bbHideWindow();
649 this->bbSetStatus(MODIFIED);
653 if ( ( bbBoxProcessModeIsReactive() ||
654 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
657 bbtkDebugMessage("modified",2,
658 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
659 this->bbSetStatus(MODIFIED);
660 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
663 //else if ( bbGetStatus() == MODIFIED ) //! this->bbIsUptodate())
665 // bbtkDebugMessage("modified",2,"-> Already modified"<<std::endl);
671 bbtkDebugMessage("modified",2,"-> Status set to modified"<<std::endl);
672 this->bbSetStatus(MODIFIED);
675 this->bbSignalOutputModification(false);
677 bbtkDebugMessageDec("process",5,
678 "<= BlackBox::bbSetModifiedStatus("<<c<<") ["
679 <<bbGetFullName()<<"]"<<std::endl);
682 //=========================================================================
684 //=========================================================================
685 void BlackBox::bbSignalOutputModification(bool reaction)
687 bbtkDebugMessageInc("change",5,
688 "=> BlackBox::bbSignalOutputModification("
690 <<bbGetFullName()<<"]"<<std::endl);
692 OutputConnectorMapType::iterator i;
693 for ( i = bbGetOutputConnectorMap().begin();
694 i != bbGetOutputConnectorMap().end(); ++i)
696 if (i->second->GetStatus()==UPTODATE)
698 // i->second->SetStatus(MODIFIED);
699 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
703 if (reaction) bbGlobalProcessExecutionList();
705 bbtkDebugMessageDec("change",5,
706 "<= BlackBox::bbSignalOutputModification() ["
707 <<bbGetFullName()<<"]"<<std::endl);
710 //=========================================================================
711 //=========================================================================
712 void BlackBox::bbSignalOutputModification(const std::string& output,
715 bbtkDebugMessageInc("change",5,
716 "=> BlackBox::bbSignalOutputModification("
717 <<output<<","<<reaction<<") ["
718 <<bbGetFullName()<<"]"<<std::endl);
720 OutputConnectorMapType::iterator i =
721 bbGetOutputConnectorMap().find(output);
724 if ( i == bbGetOutputConnectorMap().end() )
726 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
729 if (i->second->GetStatus()==UPTODATE)
731 // i->second->SetStatus(MODIFIED);
732 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
733 // Has to notify the output "BoxChange" also
734 if (output != "BoxChange")
736 i = bbGetOutputConnectorMap().find("BoxChange");
737 if ( i != bbGetOutputConnectorMap().end() )
739 // i->second->SetStatus(MODIFIED);
740 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
743 if (reaction) bbGlobalProcessExecutionList();
746 bbtkDebugMessageDec("change",5,
747 "<= BlackBox::bbSignalOutputModification("
749 <<bbGetFullName()<<"]"<<std::endl);
752 //=========================================================================
753 //=========================================================================
754 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
757 bbtkDebugMessageInc("change",5,
758 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
759 <<bbGetFullName()<<"]"<<std::endl);
760 OutputConnectorMapType::iterator i;
761 std::vector<std::string>::const_iterator o;
762 bool changed = false;
763 for (o=output.begin();o!=output.end();++o)
765 // the output "BoxChange" must be signaled **AFTER** all others
766 if (*o == "BoxChange") continue;
767 // Look for the connector
768 i = bbGetOutputConnectorMap().find(*o);
769 if ( i == bbGetOutputConnectorMap().end() )
771 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
773 // Already OUTOFDATE : noting to do
774 if (i->second->GetStatus()==UPTODATE)
776 // i->second->SetStatus(MODIFIED);
777 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
781 // Has to notify the output "BoxChange" also
782 i = bbGetOutputConnectorMap().find("BoxChange");
783 if ( changed && (i != bbGetOutputConnectorMap().end()))
785 // Already OUTOFDATE : noting to do
786 if (i->second->GetStatus()==UPTODATE)
788 // i->second->SetStatus(MODIFIED);
789 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
790 if (reaction) bbGlobalProcessExecutionList();
794 bbtkDebugMessageDec("change",5,
795 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
796 <<bbGetFullName()<<"]"<<std::endl);
799 //=========================================================================
801 //=========================================================================
802 /// Updates the BlackBox inputs
803 /// Calls BackwardUpdate on all BlackBoxInputConnector
804 /// \returns The maximum of final IOStatus after each input update
805 IOStatus BlackBox::bbUpdateInputs()
807 bbtkDebugMessageInc("process",4,
808 "=> BlackBox::bbUpdateInputs() ["
809 <<bbGetFullName()<<"]"
812 IOStatus s = UPTODATE;
814 InputConnectorMapType::iterator i;
815 for ( i = bbGetInputConnectorMap().begin();
816 i!= bbGetInputConnectorMap().end(); ++i)
818 // if (i->first=="WinHide") continue;
819 // If input type is Void : no recurse
820 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
823 bbtkDebugMessageDec("change",2,
824 bbGetName()<<"."<<i->first
825 <<" ["<<i->second<<"] "
826 <<" status before update = '"
827 <<GetIOStatusString(i->second->GetStatus())
829 i->second->BackwardUpdate();
830 IOStatus t = i->second->GetStatus();
832 bbtkDebugMessageDec("change",2,
833 bbGetName()<<"."<<i->first
834 <<" ["<<i->second<<"] "
835 <<" status before process = '"
836 <<GetIOStatusString(i->second->GetStatus())
840 bbtkDebugMessageDec("process",4,
841 "<= BlackBox::bbUpdateInputs() ["
842 <<bbGetFullName()<<"]"
848 //=========================================================================
850 //==================================================================
851 /// Computes the final IOStatus of inputs and outputs after processing
852 void BlackBox::bbComputePostProcessStatus()
854 bbtkDebugMessageInc("process",4,
855 "=> BlackBox::bbComputePostProcessStatus() ["
856 <<bbGetFullName()<<"]"
859 IOStatus new_output_status = UPTODATE;
860 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
862 // Update the input statuses
863 InputConnectorMapType::iterator i;
864 for ( i = bbGetInputConnectorMap().begin();
865 i!= bbGetInputConnectorMap().end(); ++i)
867 IOStatus t = i->second->GetStatus();
868 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
869 // A previously MODIFIED status turns to UPTODATE
870 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
871 bbtkDebugMessage("change",2,
872 bbGetName()<<"."<<i->first<<" : "
873 << GetIOStatusString(t) << " -> "
874 << GetIOStatusString(i->second->GetStatus())
877 bbtkDebugMessage("change",2,
878 bbGetName()<<" new output status : "
879 << GetIOStatusString(new_output_status)
881 // Update the output statuses
882 OutputConnectorMapType::iterator o;
883 for ( o = bbGetOutputConnectorMap().begin();
884 o!= bbGetOutputConnectorMap().end(); ++o)
886 o->second->SetStatus(new_output_status);
889 bbtkDebugMessageInc("process",4,
890 "<= BlackBox::bbComputePostProcessStatus() ["
891 <<bbGetFullName()<<"]"
895 //==================================================================
897 //=========================================================================
898 /// Connects the input <name> to the connection c
899 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
901 bbtkDebugMessage("connection",2,
902 "==> BlackBox::bbConnectInput(\""
903 <<name<<"\","<<c->GetFullName()<<") ["
904 <<bbGetFullName()<<"]"
908 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
909 if (i==bbGetInputConnectorMap().end())
911 bbtkError("no input called '"<<name<<"'");
913 i->second->SetConnection(c);
915 // Check the status of the from.output of c
916 // to set the new status of the input
917 IOStatus s = MODIFIED;
918 if ( c->GetBlackBoxFrom()->bbGetOutputConnector(c->GetBlackBoxFromOutput()).GetStatus() == OUTOFDATE )
920 bbSetStatusAndPropagate(i->second,s);
922 bbtkDebugMessage("connection",2,
923 "<== BlackBox::bbConnectInput(\""
924 <<name<<"\","<<c->GetFullName()<<") ["
925 <<bbGetFullName()<<"]"
929 //=========================================================================
932 //=========================================================================
933 /// Connects the output <name> to the connection c
934 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
936 bbtkDebugMessage("connection",2,
937 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
938 <<c->GetFullName()<<") ["
939 <<bbGetFullName()<<"]"<<std::endl);
941 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
942 if (i==bbGetOutputConnectorMap().end())
944 bbtkError("no output called '"<<name<<"'");
946 i->second->SetConnection(c);
948 bbtkDebugMessage("connection",2,
949 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
950 <<c->GetFullName()<<") ["
951 <<bbGetFullName()<<"]"<<std::endl);
954 //=========================================================================
957 //=========================================================================
958 /// Disconnects the input <name> from the connection c
959 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
962 bbtkDebugMessage("connection",2,
963 "==> BlackBox::bbDisconnectInput(\""<<name
964 <<"\","<<c->GetFullName()<<") ["
965 <<bbGetFullName()<<"]"
971 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
975 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
976 if (i==bbGetInputConnectorMap().end())
978 bbtkError("no input called '"<<name<<"'");
980 i->second->UnsetConnection(c);
982 bbtkDebugMessage("connection",2,
983 "<== BlackBox::bbDisconnectInput(\""<<name
984 <<"\","<<c->GetFullName()<<") ["
985 <<bbGetFullName()<<"]"
989 //=========================================================================
992 //=========================================================================
993 /// Disconnects the output <name> from the connection c
994 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
996 bbtkDebugMessage("connection",2,
997 "==> BlackBox::bbDisconnectOutput(\""<<name
998 <<"\","<<c->GetFullName()<<") ["
999 <<bbGetFullName()<<"]"
1004 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1008 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1009 if (i==bbGetOutputConnectorMap().end())
1011 bbtkError("no output called '"<<name<<"'");
1013 i->second->UnsetConnection(c);
1015 bbtkDebugMessage("connection",2,
1016 "<== BlackBox::bbDisconnectOutput(\""<<name
1017 <<"\","<<c->GetFullName()<<") ["
1018 <<bbGetFullName()<<"]"
1021 //=========================================================================
1024 //=========================================================================
1026 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1028 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1030 //=========================================================================
1033 //=========================================================================
1034 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1037 // Looks for the adaptor
1038 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1041 Package::Pointer p = bbGetDescriptor()->GetPackage();
1042 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1044 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1045 BlackBox::Pointer a;
1049 bbGetOutputType(output),
1050 typeid(std::string),
1052 } catch (bbtk::Exception e)
1057 a->bbSetInput("In",bbGetOutput(output));
1059 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1061 v="? (no adaptor found)";
1066 v="? (no factory found)";
1072 v = bbGetOutput(output).unsafe_get<std::string>() ;
1076 //=========================================================================
1078 //=========================================================================
1079 std::string BlackBox::bbGetInputAsString( const std::string &input )
1082 // Looks for the adaptor
1083 if (bbGetInputType(input) != typeid(std::string))
1086 Package::Pointer p = bbGetDescriptor()->GetPackage();
1087 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1089 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1090 BlackBox::Pointer a;
1094 bbGetInputType(input),
1095 typeid(std::string),
1097 }catch (bbtk::Exception e)
1103 a->bbSetInput("In",bbGetInput(input));
1105 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1109 v="? (no adaptor found)";
1114 v="? (no factory found)";
1119 v = bbGetInput(input).unsafe_get<std::string>() ;
1123 //=======================================================================
1125 //=======================================================================
1126 // Replaces substrings "<" by "["
1127 void SubsBrackets ( std::string& s )
1129 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1130 std::string ss("<");
1131 std::string::size_type pos = 0;
1133 std::string cr("[");
1134 while ( pos != std::string::npos )
1136 // std::cout << "*** find one "<<std::endl;
1137 s.replace(pos,1,cr.c_str(),1);
1138 pos = s.find(ss, pos);
1144 while ( pos != std::string::npos )
1146 // std::cout << "*** find one "<<std::endl;
1147 s.replace(pos,1,cr.c_str(),1);
1148 pos = s.find(ss, pos);
1154 while ( pos != std::string::npos )
1156 // std::cout << "*** find one "<<std::endl;
1157 s.replace(pos,1,cr.c_str(),1);
1158 pos = s.find(ss, pos);
1159 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1161 //=======================================================================
1163 //=========================================================================
1164 /// Write Graphviz-dot description in file
1165 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1166 BlackBox::Pointer parentblackbox,
1167 int detail, int level,
1168 bool instanceOrtype,
1169 bool relative_link )
1172 InputConnectorMapType::iterator i;
1174 std::string labelStr;
1175 std::string valueStr("");
1178 labelStr = bbGetName() ;
1180 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1182 labelStr = bbGetName();
1183 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1186 SubsBrackets(labelStr);
1189 labelStr = labelStr + " | {{ ";
1190 std::string tempStrTypeName;
1193 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1197 labelStr=labelStr+" | ";
1200 if (instanceOrtype==true)
1202 valueStr = this->bbGetInputAsString(i->first) + " = ";
1204 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1205 tempStrTypeName=id->GetTypeName();
1206 SubsBrackets(tempStrTypeName);
1207 std::string Name(i->first);
1209 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1211 labelStr=labelStr+ " } | {";
1213 OutputConnectorMapType::iterator ii;
1214 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1218 labelStr=labelStr+" | ";
1221 if (instanceOrtype==true)
1223 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1225 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1226 tempStrTypeName=id->GetTypeName();
1227 SubsBrackets(tempStrTypeName);
1228 std::string Name(ii->first);
1230 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1232 labelStr = labelStr+ " } }" ;
1236 bbWriteDotInputOutputName(ff,true,detail,level);
1237 std::string tmp ( bbGetTypeName() );
1241 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1243 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1245 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1246 // std::cout << labelStr << std::endl;
1249 if (GetThisPointer<BlackBox>()!=parentblackbox){
1250 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1254 Connection* con = i->second->GetConnection();
1256 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1257 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1259 a->bbWriteDotInputOutputName(ff,false,detail,level);
1262 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1265 b->bbWriteDotInputOutputName(ff,true,detail,level);
1268 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1270 fprintf(ff,"%s\n",";");
1274 } // if parentblackbox
1276 //=========================================================================
1281 //=========================================================================
1282 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1283 int detail, int level
1284 /*,Factory *factory*/ )
1287 if (this->bbGetDescriptor()->GetPackage())
1289 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1290 this->bbGetDescriptor()->GetPackage()->GetName()
1291 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1295 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1300 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1301 <<mMinOutputChangeTime<<"]"<<std::endl);
1305 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1306 <<mMinOutputChangeTime<<"]"<<std::endl);
1309 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1310 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1312 std::vector<std::string> iname;
1313 std::vector<std::string> ivalue;
1314 std::vector<std::string> iconn;
1315 std::vector<std::string> istatus;
1317 InputConnectorMapType::iterator i;
1318 unsigned int namelmax = 0;
1319 unsigned int valuelmax = 0;
1320 // unsigned int connlmax = 0;
1321 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1323 iname.push_back(i->first);
1324 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1325 ivalue.push_back(bbGetInputAsString(i->first));
1326 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1328 Connection* con = i->second->GetConnection();
1330 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1332 s += con->GetOriginalBlackBoxFromOutput();
1335 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1337 OutputConnectorMapType::iterator o;
1338 std::vector<std::string> oname;
1339 std::vector<std::string> ovalue;
1340 std::vector<std::vector<std::string> > oconn;
1341 std::vector<std::string> ostatus;
1342 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1344 oname.push_back(o->first);
1345 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1346 ovalue.push_back(bbGetOutputAsString(o->first));
1347 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1348 std::vector<std::string> ss;
1349 const std::vector<Connection*>& con
1350 = o->second->GetConnectionVector();
1351 std::vector<Connection*>::const_iterator c;
1352 for (c=con.begin();c!=con.end();++c)
1355 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1357 s += (*c)->GetOriginalBlackBoxToInput();
1360 oconn.push_back(ss);
1361 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1365 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1367 bbtkMessage("Help",1," * No inputs"<<std::endl);
1369 std::vector<std::string>::iterator i1,i2,i3,i4;
1370 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1371 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1372 ++i1,++i2,++i3,++i4)
1374 std::string name(*i1);
1376 name.append(1+namelmax-name.size(),' ');
1377 std::string value(*i2);
1379 value.append(1+valuelmax-value.size(),' ');
1381 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1384 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1385 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1389 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1391 bbtkMessage("Help",1," * No outputs"<<std::endl);
1393 std::vector<std::vector<std::string> >::iterator i5;
1395 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1396 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1397 ++i1,++i2,++i4,++i5)
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 std::string pref = " '"+name+" = '"+value;
1410 for (i3=i5->begin();i3!=i5->end();++i3)
1412 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1413 pref.replace(0,pref.size(),pref.size(),' ');
1416 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1420 //=========================================================================
1422 static bool bbmgGlobalProcessingExecutionList = false;
1424 //=========================================================================
1425 void BlackBox::bbGlobalProcessExecutionList()
1427 bbtkDebugMessageInc("process",3,
1428 "=> BlackBox::bbGlobalProcessExecutionList()"
1430 if (bbmgGlobalProcessingExecutionList)
1432 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1435 bbmgGlobalProcessingExecutionList = true;
1437 std::set<BlackBox::WeakPointer>::iterator i;
1438 while (bbmgExecutionList.size()>0)
1440 i = bbmgExecutionList.begin();
1441 BlackBox::WeakPointer p = *i;
1442 bbmgExecutionList.erase(i);
1445 bbtkDebugMessage("process",4,
1447 p.lock()->bbGetFullName()<<std::endl);
1448 p.lock()->bbExecute(true);
1452 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1456 bbmgExecutionList.clear();
1457 bbtkDebugMessageDec("process",3,
1458 "<= BlackBox::bbGlobalProcessExecutionList()"
1461 bbmgGlobalProcessingExecutionList = false;
1464 //=========================================================================
1466 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1468 return bbmgSomeBoxExecuting;
1471 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1473 bbmgSomeBoxExecuting = b;
1476 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1478 bbmgFreezeExecution = b;
1481 bool BlackBox::bbGlobalGetFreezeExecution()
1483 return bbmgFreezeExecution;
1486 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1488 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1489 if (bbmgGlobalProcessingExecutionList)
1491 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1493 bbmgExecutionList.insert(b);
1497 //=========================================================================
1499 //=========================================================================
1500 void BlackBox::Check(bool recursive)
1502 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1503 <<"] ... OK"<<std::endl);
1505 //=========================================================================
1507 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1509 bbtk::BlackBoxInputConnector *cc;
1510 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1511 if (cc->GetConnection()!=NULL)
1513 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1519 } // EO namespace bbtk