1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/04/30 14:31:31 $
6 Version: $Revision: 1.43 $
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"
53 static bool bbmgSomeBoxExecuting = false;
54 static bool bbmgFreezeExecution = false;
55 static std::set<BlackBox::WeakPointer> bbmgExecutionList;
57 //=========================================================================
59 BlackBox::Deleter::Deleter()
62 //=========================================================================
64 //=========================================================================
65 int BlackBox::Deleter::Delete(Object* p)
67 BlackBox* b = dynamic_cast<BlackBox*>(p);
70 bbtkInternalError("BlackBox::Deleter::Delete("<<p->GetObjectName()
72 <<"dynamic cast to BlackBox* failed !");
74 std::string name = p->GetObjectName();//b->bbGetNameWithParent();
75 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
78 BlackBoxDescriptor::WeakPointer desc = b->bbGetDescriptor();
79 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : deleting black box"<<std::endl);
81 int refs = b->bbDelete();
83 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : releasing descriptor"<<std::endl);
87 Package::WeakPointer pack = desc.lock()->GetPackage();
90 Package::ReleaseBlackBoxDescriptor(pack,desc);
94 bbtkDebugMessage("object",2,"##> BlackBox::Deleter(\""<<name<<"\") : descriptor package expired (was not held by a package and the box was the last instance)"<<std::endl);
99 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);
101 bbtkDebugMessage("object",2,"<## BlackBox::Deleter(\""<<name<<"\")"<<std::endl);
104 //=========================================================================
106 //=========================================================================
107 BlackBox::BlackBox(const std::string &name)
109 // bbmStatus(MODIFIED),
110 bbmConstructed(false),
113 bbmBoxProcessMode("Pipeline"),
117 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
118 <<name<<"\")"<<std::endl);
119 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox(\""
120 <<name<<"\")"<<std::endl);
122 //=========================================================================
124 //=========================================================================
125 BlackBox::BlackBox(const BlackBox&)
128 //=========================================================================
129 BlackBox::BlackBox(BlackBox& from, const std::string &name)
131 // bbmStatus(from.bbmStatus),
132 bbmConstructed(false),
135 bbmBoxProcessMode(from.bbmBoxProcessMode),
139 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox("
140 <<from.bbGetFullName()<<",\""
141 <<name<<"\")"<<std::endl);
142 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox("
143 <<from.bbGetFullName()<<",\""
144 <<name<<"\")"<<std::endl);
146 //=========================================================================
149 //=========================================================================
150 BlackBox::~BlackBox()
152 bbtkDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
154 this->bbDesallocateConnectors();
155 bbtkDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<<bbmName
158 //=========================================================================
162 //=========================================================================
163 std::string BlackBox::bbGetFullName() const
165 return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
167 //=========================================================================
171 //=========================================================================
172 /// Returns the name with the name of the parent prepended if any
173 std::string BlackBox::bbGetNameWithParent() const
175 if (bbmParent.lock())
177 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
184 //=========================================================================
186 //=========================================================================
187 /// Prints the Help on the BlackBox type
188 void BlackBox::bbGetHelp(bool full) const
190 bbGetDescriptor()->GetHelp(full);
192 //=========================================================================
195 //=========================================================================
196 /// Returns true if the UserBlackBox has an input of name name
197 bool BlackBox::bbHasInput(const std::string& name) const
199 bbtkDebugMessageInc("Kernel",8,
200 "BlackBox::bbHasInput(\""
201 <<name<<"\") ["<<bbGetFullName()<<"]"
203 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
204 != bbGetDescriptor()->GetInputDescriptorMap().end());
205 bbtkDebugDecTab("Kernel",8);
208 //=========================================================================
211 //=========================================================================
212 /// Returns true if the UserBlackBox has an output of name name
213 bool BlackBox::bbHasOutput(const std::string& name) const
215 bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
216 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
217 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
218 != bbGetDescriptor()->GetOutputDescriptorMap().end());
219 bbtkDebugDecTab("Kernel",8);
222 //=========================================================================
225 //=========================================================================
226 /// Gets the output type of a given name
227 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
229 bbtkDebugMessageInc("Kernel",8,
230 "BlackBox::bbGetOutputType(\""
231 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
232 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
233 bbtkDebugDecTab("Kernel",8);
236 //=========================================================================
238 //=========================================================================
239 /// Gets the input type of a given name
240 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
242 bbtkDebugMessageInc("Kernel",8,
243 "BlackBox::bbGetInputType(\""
244 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
245 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
246 bbtkDebugDecTab("Kernel",8);
249 //=========================================================================
252 //=========================================================================
253 /// Allocates the i/o connectors of the black box
254 void BlackBox::bbAllocateConnectors()
256 bbtkDebugMessageInc("Kernel",8,
257 "BlackBox::bbAllocateConnectors() ["
258 <<bbGetFullName()<<"]"
260 const BlackBoxDescriptor::InputDescriptorMapType& imap
261 = bbGetDescriptor()->GetInputDescriptorMap();
262 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
263 for ( i = imap.begin(); i != imap.end(); ++i )
265 bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
266 bbGetInputConnectorMap()[i->second->GetName()]
267 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
269 const BlackBoxDescriptor::OutputDescriptorMapType& omap
270 = bbGetDescriptor()->GetOutputDescriptorMap();
271 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
272 for ( o = omap.begin(); o != omap.end(); ++o )
274 bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
275 bbGetOutputConnectorMap()[o->second->GetName()]
276 = new BlackBoxOutputConnector();
278 bbtkDebugDecTab("Kernel",8);
280 //=========================================================================
283 //=========================================================================
284 /// Desallocates the i/o connectors of the black box
285 void BlackBox::bbDesallocateConnectors()
287 bbtkDebugMessageInc("Kernel",8,
288 "BlackBox::bbDesallocateConnectors()"
291 InputConnectorMapType::const_iterator i;
292 for ( i = bbGetInputConnectorMap().begin();
293 i != bbGetInputConnectorMap().end(); ++i )
295 bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
298 OutputConnectorMapType::const_iterator o;
299 for ( o = bbGetOutputConnectorMap().begin();
300 o != bbGetOutputConnectorMap().end(); ++o )
302 bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
306 bbtkDebugDecTab("Kernel",8);
309 //=========================================================================
312 //=========================================================================
313 /// Copies the input / output values from another box
314 void BlackBox::bbCopyIOValues(BlackBox& from)
316 bbtkDebugMessageInc("Kernel",1,
317 "BlackBox::bbCopyIOValues("
318 <<from.bbGetFullName()<<") ["
319 <<bbGetFullName()<<"]"<<std::endl);
320 // copies the input values
321 const BlackBoxDescriptor::InputDescriptorMapType& imap
322 = bbGetDescriptor()->GetInputDescriptorMap();
323 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
324 for ( i = imap.begin(); i != imap.end(); ++i )
326 if (! i->second->GetCopyConstruct() ) continue;
327 std::string input = i->second->GetName();
328 bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
329 this->bbSetInput(input, from.bbGetInput(input) );
331 // copies the output values
332 const BlackBoxDescriptor::OutputDescriptorMapType& omap
333 = bbGetDescriptor()->GetOutputDescriptorMap();
334 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
335 for ( o = omap.begin(); o != omap.end(); ++o )
337 if (! o->second->GetCopyConstruct() ) continue;
338 std::string output = o->second->GetName();
339 bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
340 this->bbSetOutput(output, from.bbGetOutput(output) );
343 bbtkDebugDecTab("Kernel",9);
346 //=========================================================================
350 //=========================================================================
351 bool BlackBox::bbCanReact() const
353 return ( bbGlobalGetSomeBoxExecuting()
355 || Wx::IsSomeWindowAlive()
359 //=========================================================================
363 //=========================================================================
364 /// User overloadable destruction method of a black box
365 void BlackBox::bbUserDelete()
367 bbtkDebugMessage("process",5,
368 "=> BlackBox::bbUserDelete() ["
369 <<bbGetFullName()<<"]"
370 <<" : not overloaded; using standard deletion"
374 //=========================================================================
377 //=========================================================================
378 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
380 const std::string& p = bbmBoxProcessMode;
382 (p == "P") || (p == "p") ||
383 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
385 (p == "A") || (p == "a") ||
386 (p == "Always") || (p == "always") ) return Always;
388 (p == "R") || (p == "r") ||
389 (p == "Reactive") || (p == "reactive") ) return Reactive;
392 (p == "F") || (p == "f") ||
393 (p == "Flash") || (p == "flash") ) return Flash;
395 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
396 <<"' unknown. Possible values : "
397 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
398 <<"'1'/'A'/'a'/'Always'/'always' | "
399 <<"'2'/'R'/'r'/'Reactive'/'reactive'"
400 // <<"'3'/'F'/'f'/'Flash'/'flash'"
403 //=========================================================================
405 //=========================================================================
406 bool BlackBox::bbBoxProcessModeIsReactive() const
408 return (bbGetBoxProcessModeValue() == Reactive);
410 //=========================================================================
412 //=========================================================================
413 bool BlackBox::bbBoxProcessModeIsAlways() const
415 return (bbGetBoxProcessModeValue() == Always);
417 //=========================================================================
422 //=========================================================================
423 void BlackBox::bbAddOutputObserver(const std::string& output,
424 OutputChangeCallbackType f)
426 bbGetOutputConnector(output).AddChangeObserver(f);
428 //=========================================================================
430 //=========================================================================
431 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
432 OutputChangeCallbackType f)
434 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
436 //=========================================================================
440 //=========================================================================
441 /// Sets the ChangeTime of input
442 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
445 bbtkDebugMessage("change",1,
446 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
447 <<bbGetFullName()<<"]"<<std::endl);
449 // If new time is greater than old one
450 if ( c->SetChangeTime(t) )
452 bool was_up_to_date = bbIsUpToDate();
453 // If new time is greater than the old max time of inputs
454 if ( mMaxInputChangeTime.Set(t) )
456 // If the box turned out-of-date
457 if ( was_up_to_date && bbIsOutOfDate() )
460 if ( ( bbBoxProcessModeIsReactive() ||
461 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
464 bbtkDebugMessage("change",2,
467 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
469 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
471 // Have to propagate the modification to aval boxes
472 OutputConnectorMapType::iterator i;
473 for (i = bbGetOutputConnectorMap().begin();
474 i != bbGetOutputConnectorMap().end();
477 i->second->SetChangeTime(t);
479 // update the MinOutputChangeTime
480 mMinOutputChangeTime.Set(t);
485 //=========================================================================
487 //=========================================================================
488 /// Sets the ChangeTime of output
489 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
492 bbtkDebugMessage("change",1,
493 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
494 <<bbGetFullName()<<"]"<<std::endl);
498 // c->GetChangeTime() = t;
499 // bbUpdateMinOutputChangeTime(t);
503 //=========================================================================
507 //=========================================================================
508 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
512 if ( t > mMaxInputChangeTime )
514 mMaxInputChangeTime = t;
515 if ( mMinOutputChangeTime > mMaxInputChangeTime )
522 //=========================================================================
524 //=========================================================================
525 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
527 ChangeTime old = mMinOutputChangeTime;
528 mMinOutputChangeTime = MAXLONG;
529 OutputConnectorMapType::iterator i;
530 for (i = bbGetOutputConnectorMap.begin();
531 i != bbGetOutputConnectorMap.end();
534 if (i->second->GetChangeTime() < mMinOutputChangeTime)
535 mMinOutputChangeTime = i->second->GetChangeTime();
537 if ( mMinOutputChangeTime < old )
542 //=========================================================================
545 //=========================================================================
546 /// Signals that the BlackBox has been modified through
547 /// the input connector c
548 /// and propagates it downward
549 /// ** NOT USER INTENDED **
550 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
553 bbtkDebugMessageInc("change",5,
554 "=> BlackBox::bbSetStatusAndPropagate(input,"
555 <<GetIOStatusString(s)<<") ["
556 <<bbGetFullName()<<"]"<<std::endl);
558 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
563 if (bbGetBoxProcessModeValue() == Flash)
569 OutputConnectorMapType::const_iterator o;
570 for ( o = bbGetOutputConnectorMap().begin();
571 o != bbGetOutputConnectorMap().end(); ++o )
573 if (o->second->GetStatus()==UPTODATE)
575 o->second->SetStatus(OUTOFDATE);
576 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
580 if ( ( bbBoxProcessModeIsReactive() ||
581 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
584 bbtkDebugMessage("change",2,
585 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
586 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
588 bbtkDebugMessageInc("change",5,
589 "<= BlackBox::bbSetStatusAndPropagate(input) ["
590 <<bbGetFullName()<<"]"<<std::endl);
592 //=========================================================================
595 //=========================================================================
596 void BlackBox::bbSignalOutputModification(bool reaction)
598 bbtkDebugMessageInc("change",5,
599 "=> BlackBox::bbSignalOutputModification("
601 <<bbGetFullName()<<"]"<<std::endl);
603 OutputConnectorMapType::iterator i;
604 for ( i = bbGetOutputConnectorMap().begin();
605 i != bbGetOutputConnectorMap().end(); ++i)
607 // std::cout << "Stat = "
608 //<<GetIOStatusString(i->second->GetStatus())
610 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
611 // See bbtkSampleOutputObserver
612 // if (i->second->GetStatus()==UPTODATE)
614 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
618 if (reaction) bbGlobalProcessExecutionList();
620 bbtkDebugMessageDec("change",5,
621 "<= BlackBox::bbSignalOutputModification() ["
622 <<bbGetFullName()<<"]"<<std::endl);
625 //=========================================================================
626 //=========================================================================
627 void BlackBox::bbSignalOutputModification(const std::string& output,
630 bbtkDebugMessageInc("change",5,
631 "=> BlackBox::bbSignalOutputModification("
632 <<output<<","<<reaction<<") ["
633 <<bbGetFullName()<<"]"<<std::endl);
635 OutputConnectorMapType::iterator i =
636 bbGetOutputConnectorMap().find(output);
639 if ( i == bbGetOutputConnectorMap().end() )
641 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
644 // if (i->second->GetStatus()==UPTODATE)
646 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
647 // Has to notify the output "BoxChange" also
648 if (output != "BoxChange")
650 i = bbGetOutputConnectorMap().find("BoxChange");
651 if ( i != bbGetOutputConnectorMap().end() )
653 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
656 if (reaction) bbGlobalProcessExecutionList();
659 bbtkDebugMessageDec("change",5,
660 "<= BlackBox::bbSignalOutputModification("
662 <<bbGetFullName()<<"]"<<std::endl);
665 //=========================================================================
666 //=========================================================================
667 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
670 bbtkDebugMessageInc("change",5,
671 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
672 <<bbGetFullName()<<"]"<<std::endl);
673 OutputConnectorMapType::iterator i;
674 std::vector<std::string>::const_iterator o;
675 bool changed = false;
676 for (o=output.begin();o!=output.end();++o)
678 // the output "BoxChange" must be signaled **AFTER** all others
679 if (*o == "BoxChange") continue;
680 // Look for the connector
681 i = bbGetOutputConnectorMap().find(*o);
682 if ( i == bbGetOutputConnectorMap().end() )
684 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
687 // if (i->second->GetStatus()==UPTODATE)
689 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
693 // Has to notify the output "BoxChange" also
694 i = bbGetOutputConnectorMap().find("BoxChange");
695 if ( changed && (i != bbGetOutputConnectorMap().end()))
697 // if (i->second->GetStatus()==UPTODATE)
699 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
700 if (reaction) bbGlobalProcessExecutionList();
704 bbtkDebugMessageDec("change",5,
705 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
706 <<bbGetFullName()<<"]"<<std::endl);
709 //=========================================================================
717 //=========================================================================
718 /// Main processing method of the box.
719 void BlackBox::bbExecute(bool force)
721 bbtkDebugMessageInc("process",2,
722 "=> BlackBox::bbExecute("<<(int)force<<") ["
723 <<bbGetFullName()<<"]"<<std::endl);
725 // If already executing : return
727 if (bbGetExecuting())
729 bbtkDebugMessage("process",2,
730 " -> already executing : abort"<<std::endl);
735 // If execution frozen : return
736 if (bbGlobalGetFreezeExecution())
738 bbtkDebugMessage("process",2,
739 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
744 // If force is true then update is triggered even if the box is UPTODATE
745 // if (force) bbSetModifiedStatus();
747 // Calls the main recursive execution method
748 bbRecursiveExecute(Connection::Pointer());
750 bbtkDebugMessageDec("process",2,
751 "<= BlackBox::bbExecute() ["
752 <<bbGetFullName()<<"]"<<std::endl);
754 //=========================================================================
757 //=========================================================================
758 /// Main recursive processing method of the box.
759 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
761 bbtkDebugMessageInc("process",3,
762 "=> BlackBox::bbRecursiveExecute("
763 <<(caller?caller->GetFullName():"0")<<") ["
764 <<bbGetFullName()<<"]"<<std::endl);
766 // If already executing : return
767 if (bbGetExecuting())
769 bbtkDebugMessage("process",3,
770 " -> already executing : abort"<<std::endl);
774 // If not constructed do it
777 this->bbConstructor();
778 bbmConstructed = true;
782 bbSetExecuting(true);
783 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
784 bbGlobalSetSomeBoxExecuting(true);
786 // Creates the window if the black box has one
787 this->bbCreateWindow();
789 // Updates its inputs
790 IOStatus s = bbUpdateInputs();
792 if ( (s != UPTODATE) ||
793 bbBoxProcessModeIsAlways() )
795 // Displays the window (WxBlackbox)
796 // bbShowWindow(caller);
798 // Actual processing (virtual)
802 // Update the I/O statuses
803 bbComputePostProcessStatus();
807 // Test output status...
808 OutputConnectorMapType::iterator o;
809 for ( o = bbGetOutputConnectorMap().begin();
810 o!= bbGetOutputConnectorMap().end(); ++o)
812 if (o->second->GetStatus() != UPTODATE)
814 bbtkWarning("BlackBox::bbRecursiveExecute ["
816 <<"] : all inputs are Up-to-date but output '"
817 <<o->first<<"' is Out-of-date ???");
821 bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
825 // Shows the window if the black box has one
826 this->bbShowWindow();
829 bbtkDebugMessage("process",3,
830 "<= BlackBox::bbRecursiveExecute() ["
831 <<bbGetFullName()<<"]"<<std::endl);
833 bbSetExecuting(false);
834 bbGlobalSetSomeBoxExecuting(wasExecuting);
839 //=========================================================================
845 //=========================================================================
846 /// Updates the BlackBox inputs
847 /// Calls RecursiveExecute on all BlackBoxInputConnector
848 /// \returns The maximum of final IOStatus after each input update
849 IOStatus BlackBox::bbUpdateInputs()
851 bbtkDebugMessageInc("process",4,
852 "=> BlackBox::bbUpdateInputs() ["
853 <<bbGetFullName()<<"]"
856 IOStatus s = UPTODATE;
858 InputConnectorMapType::iterator i;
859 for ( i = bbGetInputConnectorMap().begin();
860 i!= bbGetInputConnectorMap().end(); ++i)
862 // if (i->first=="WinHide") continue;
863 // If input type is Void : no recurse
864 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
867 bbtkDebugMessageDec("change",2,
868 bbGetName()<<"."<<i->first
869 <<" ["<<i->second<<"] "
870 <<" status before update = '"
871 <<GetIOStatusString(i->second->GetStatus())
873 i->second->RecursiveExecute();
874 IOStatus t = i->second->GetStatus();
876 bbtkDebugMessageDec("change",2,
877 bbGetName()<<"."<<i->first
878 <<" ["<<i->second<<"] "
879 <<" status before process = '"
880 <<GetIOStatusString(i->second->GetStatus())
884 bbtkDebugMessageDec("process",4,
885 "<= BlackBox::bbUpdateInputs() ["
886 <<bbGetFullName()<<"]"
892 //=========================================================================
894 //==================================================================
895 /// Computes the final IOStatus of inputs and outputs after processing
896 void BlackBox::bbComputePostProcessStatus()
898 bbtkDebugMessageInc("process",4,
899 "=> BlackBox::bbComputePostProcessStatus() ["
900 <<bbGetFullName()<<"]"
903 IOStatus new_output_status = UPTODATE;
904 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
906 // Update the input statuses
907 InputConnectorMapType::iterator i;
908 for ( i = bbGetInputConnectorMap().begin();
909 i!= bbGetInputConnectorMap().end(); ++i)
911 IOStatus t = i->second->GetStatus();
912 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
913 // A previously MODIFIED status turns to UPTODATE
914 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
915 bbtkDebugMessage("change",2,
916 bbGetName()<<"."<<i->first<<" : "
917 << GetIOStatusString(t) << " -> "
918 << GetIOStatusString(i->second->GetStatus())
921 bbtkDebugMessage("change",2,
922 bbGetName()<<" new output status : "
923 << GetIOStatusString(new_output_status)
925 // Update the output statuses
926 OutputConnectorMapType::iterator o;
927 for ( o = bbGetOutputConnectorMap().begin();
928 o!= bbGetOutputConnectorMap().end(); ++o)
930 o->second->SetStatus(new_output_status);
933 bbtkDebugMessageInc("process",4,
934 "<= BlackBox::bbComputePostProcessStatus() ["
935 <<bbGetFullName()<<"]"
939 //==================================================================
941 //=========================================================================
942 /// Connects the input <name> to the connection c
943 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
945 bbtkDebugMessage("connection",2,
946 "==> BlackBox::bbConnectInput(\""
947 <<name<<"\","<<c->GetFullName()<<") ["
948 <<bbGetFullName()<<"]"
952 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
953 if (i==bbGetInputConnectorMap().end())
955 bbtkError("no input called '"<<name<<"'");
957 i->second->SetConnection(c);
958 // The input *MUST* be set OUTOFDATE to update its input on next execution
959 bbSetStatusAndPropagate(i->second,OUTOFDATE);
961 bbtkDebugMessage("connection",2,
962 "<== BlackBox::bbConnectInput(\""
963 <<name<<"\","<<c->GetFullName()<<") ["
964 <<bbGetFullName()<<"]"
968 //=========================================================================
971 //=========================================================================
972 /// Connects the output <name> to the connection c
973 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
975 bbtkDebugMessage("connection",2,
976 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
977 <<c->GetFullName()<<") ["
978 <<bbGetFullName()<<"]"<<std::endl);
980 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
981 if (i==bbGetOutputConnectorMap().end())
983 bbtkError("no output called '"<<name<<"'");
985 i->second->SetConnection(c);
987 bbtkDebugMessage("connection",2,
988 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
989 <<c->GetFullName()<<") ["
990 <<bbGetFullName()<<"]"<<std::endl);
993 //=========================================================================
996 //=========================================================================
997 /// Disconnects the input <name> from the connection c
998 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
1001 bbtkDebugMessage("connection",2,
1002 "==> BlackBox::bbDisconnectInput(\""<<name
1003 <<"\","<<c->GetFullName()<<") ["
1004 <<bbGetFullName()<<"]"
1010 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1014 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
1015 if (i==bbGetInputConnectorMap().end())
1017 bbtkError("no input called '"<<name<<"'");
1019 i->second->UnsetConnection(c);
1021 bbtkDebugMessage("connection",2,
1022 "<== BlackBox::bbDisconnectInput(\""<<name
1023 <<"\","<<c->GetFullName()<<") ["
1024 <<bbGetFullName()<<"]"
1028 //=========================================================================
1031 //=========================================================================
1032 /// Disconnects the output <name> from the connection c
1033 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
1035 bbtkDebugMessage("connection",2,
1036 "==> BlackBox::bbDisconnectOutput(\""<<name
1037 <<"\","<<c->GetFullName()<<") ["
1038 <<bbGetFullName()<<"]"
1043 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1047 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1048 if (i==bbGetOutputConnectorMap().end())
1050 bbtkError("no output called '"<<name<<"'");
1052 i->second->UnsetConnection(c);
1054 bbtkDebugMessage("connection",2,
1055 "<== BlackBox::bbDisconnectOutput(\""<<name
1056 <<"\","<<c->GetFullName()<<") ["
1057 <<bbGetFullName()<<"]"
1060 //=========================================================================
1063 //=========================================================================
1065 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1067 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1069 //=========================================================================
1072 //=========================================================================
1073 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1076 // Looks for the adaptor
1077 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1080 Package::Pointer p = bbGetDescriptor()->GetPackage();
1081 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1083 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1084 BlackBox::Pointer a;
1088 bbGetOutputType(output),
1089 typeid(std::string),
1091 } catch (bbtk::Exception e)
1096 a->bbSetInput("In",bbGetOutput(output));
1098 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1100 v="? (no adaptor found)";
1105 v="? (no factory found)";
1111 v = bbGetOutput(output).unsafe_get<std::string>() ;
1115 //=========================================================================
1117 //=========================================================================
1118 std::string BlackBox::bbGetInputAsString( const std::string &input )
1121 // Looks for the adaptor
1122 if (bbGetInputType(input) != typeid(std::string))
1125 Package::Pointer p = bbGetDescriptor()->GetPackage();
1126 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1128 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1129 BlackBox::Pointer a;
1133 bbGetInputType(input),
1134 typeid(std::string),
1136 }catch (bbtk::Exception e)
1142 a->bbSetInput("In",bbGetInput(input));
1144 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1148 v="? (no adaptor found)";
1153 v="? (no factory found)";
1158 v = bbGetInput(input).unsafe_get<std::string>() ;
1162 //=======================================================================
1164 //=======================================================================
1165 // Replaces substrings "<" by "["
1166 void SubsBrackets ( std::string& s )
1168 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1169 std::string ss("<");
1170 std::string::size_type pos = 0;
1172 std::string cr("[");
1173 while ( pos != std::string::npos )
1175 // std::cout << "*** find one "<<std::endl;
1176 s.replace(pos,1,cr.c_str(),1);
1177 pos = s.find(ss, pos);
1183 while ( pos != std::string::npos )
1185 // std::cout << "*** find one "<<std::endl;
1186 s.replace(pos,1,cr.c_str(),1);
1187 pos = s.find(ss, pos);
1193 while ( pos != std::string::npos )
1195 // std::cout << "*** find one "<<std::endl;
1196 s.replace(pos,1,cr.c_str(),1);
1197 pos = s.find(ss, pos);
1198 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1200 //=======================================================================
1202 //=========================================================================
1203 /// Write Graphviz-dot description in file
1204 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1205 BlackBox::Pointer parentblackbox,
1206 int detail, int level,
1207 bool instanceOrtype,
1208 bool relative_link )
1211 InputConnectorMapType::iterator i;
1213 std::string labelStr;
1214 std::string valueStr("");
1217 labelStr = bbGetName() ;
1219 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1221 labelStr = bbGetName();
1222 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1225 SubsBrackets(labelStr);
1228 labelStr = labelStr + " | {{ ";
1229 std::string tempStrTypeName;
1232 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1236 labelStr=labelStr+" | ";
1239 if (instanceOrtype==true)
1241 valueStr = this->bbGetInputAsString(i->first) + " = ";
1243 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1244 tempStrTypeName=id->GetTypeName();
1245 SubsBrackets(tempStrTypeName);
1246 std::string Name(i->first);
1248 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1250 labelStr=labelStr+ " } | {";
1252 OutputConnectorMapType::iterator ii;
1253 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1257 labelStr=labelStr+" | ";
1260 if (instanceOrtype==true)
1262 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1264 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1265 tempStrTypeName=id->GetTypeName();
1266 SubsBrackets(tempStrTypeName);
1267 std::string Name(ii->first);
1269 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1271 labelStr = labelStr+ " } }" ;
1275 bbWriteDotInputOutputName(ff,true,detail,level);
1276 std::string tmp ( bbGetTypeName() );
1280 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1282 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1284 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1285 // std::cout << labelStr << std::endl;
1288 if (GetThisPointer<BlackBox>()!=parentblackbox){
1289 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1293 Connection* con = i->second->GetConnection();
1295 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1296 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1298 a->bbWriteDotInputOutputName(ff,false,detail,level);
1301 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1304 b->bbWriteDotInputOutputName(ff,true,detail,level);
1307 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1309 fprintf(ff,"%s\n",";");
1313 } // if parentblackbox
1315 //=========================================================================
1320 //=========================================================================
1321 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1322 int detail, int level
1323 /*,Factory *factory*/ )
1326 if (this->bbGetDescriptor()->GetPackage())
1328 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1329 this->bbGetDescriptor()->GetPackage()->GetName()
1330 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1334 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1339 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1340 <<mMinOutputChangeTime<<"]"<<std::endl);
1344 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1345 <<mMinOutputChangeTime<<"]"<<std::endl);
1348 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1349 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1351 std::vector<std::string> iname;
1352 std::vector<std::string> ivalue;
1353 std::vector<std::string> iconn;
1354 std::vector<std::string> istatus;
1356 InputConnectorMapType::iterator i;
1357 unsigned int namelmax = 0;
1358 unsigned int valuelmax = 0;
1359 // unsigned int connlmax = 0;
1360 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1362 iname.push_back(i->first);
1363 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1364 ivalue.push_back(bbGetInputAsString(i->first));
1365 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1367 Connection* con = i->second->GetConnection();
1369 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1371 s += con->GetOriginalBlackBoxFromOutput();
1374 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1376 OutputConnectorMapType::iterator o;
1377 std::vector<std::string> oname;
1378 std::vector<std::string> ovalue;
1379 std::vector<std::vector<std::string> > oconn;
1380 std::vector<std::string> ostatus;
1381 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1383 oname.push_back(o->first);
1384 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1385 ovalue.push_back(bbGetOutputAsString(o->first));
1386 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1387 std::vector<std::string> ss;
1388 const std::vector<Connection*>& con
1389 = o->second->GetConnectionVector();
1390 std::vector<Connection*>::const_iterator c;
1391 for (c=con.begin();c!=con.end();++c)
1394 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1396 s += (*c)->GetOriginalBlackBoxToInput();
1399 oconn.push_back(ss);
1400 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1404 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1406 bbtkMessage("Help",1," * No inputs"<<std::endl);
1408 std::vector<std::string>::iterator i1,i2,i3,i4;
1409 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1410 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1411 ++i1,++i2,++i3,++i4)
1413 std::string name(*i1);
1415 name.append(1+namelmax-name.size(),' ');
1416 std::string value(*i2);
1418 value.append(1+valuelmax-value.size(),' ');
1420 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1423 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1424 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1428 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1430 bbtkMessage("Help",1," * No outputs"<<std::endl);
1432 std::vector<std::vector<std::string> >::iterator i5;
1434 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1435 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1436 ++i1,++i2,++i4,++i5)
1438 std::string name(*i1);
1440 name.append(1+namelmax-name.size(),' ');
1441 std::string value(*i2);
1443 value.append(1+valuelmax-value.size(),' ');
1445 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1448 std::string pref = " '"+name+" = '"+value;
1449 for (i3=i5->begin();i3!=i5->end();++i3)
1451 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1452 pref.replace(0,pref.size(),pref.size(),' ');
1455 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1459 //=========================================================================
1461 static bool bbmgGlobalProcessingExecutionList = false;
1463 //=========================================================================
1464 void BlackBox::bbGlobalProcessExecutionList()
1466 bbtkDebugMessageInc("process",3,
1467 "=> BlackBox::bbGlobalProcessExecutionList()"
1469 if (bbmgGlobalProcessingExecutionList)
1471 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1474 bbmgGlobalProcessingExecutionList = true;
1476 std::set<BlackBox::WeakPointer>::iterator i;
1477 while (bbmgExecutionList.size()>0)
1479 i = bbmgExecutionList.begin();
1480 BlackBox::WeakPointer p = *i;
1481 bbmgExecutionList.erase(i);
1484 bbtkDebugMessage("process",4,
1486 p.lock()->bbGetFullName()<<std::endl);
1487 p.lock()->bbExecute(true);
1491 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1495 bbmgExecutionList.clear();
1496 bbtkDebugMessageDec("process",3,
1497 "<= BlackBox::bbGlobalProcessExecutionList()"
1500 bbmgGlobalProcessingExecutionList = false;
1503 //=========================================================================
1505 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1507 return bbmgSomeBoxExecuting;
1510 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1512 bbmgSomeBoxExecuting = b;
1515 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1517 bbmgFreezeExecution = b;
1520 bool BlackBox::bbGlobalGetFreezeExecution()
1522 return bbmgFreezeExecution;
1525 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1527 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1528 if (bbmgGlobalProcessingExecutionList)
1530 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1532 bbmgExecutionList.insert(b);
1536 //=========================================================================
1538 //=========================================================================
1539 void BlackBox::Check(bool recursive)
1541 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1542 <<"] ... OK"<<std::endl);
1544 //=========================================================================
1546 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1548 bbtk::BlackBoxInputConnector *cc;
1549 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1550 if (cc->GetConnection()!=NULL)
1552 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1558 } // EO namespace bbtk