1 /*=========================================================================
3 Module: $RCSfile: bbtkBlackBox.cxx,v $
5 Date: $Date: 2009/04/08 07:56:11 $
6 Version: $Revision: 1.42 $
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 void 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);
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);
103 //=========================================================================
105 //=========================================================================
106 BlackBox::BlackBox(const std::string &name)
108 // bbmStatus(MODIFIED),
111 bbmBoxProcessMode("Pipeline"),
115 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox(\""
116 <<name<<"\")"<<std::endl);
117 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox(\""
118 <<name<<"\")"<<std::endl);
120 //=========================================================================
122 //=========================================================================
123 BlackBox::BlackBox(const BlackBox&)
126 //=========================================================================
127 BlackBox::BlackBox(BlackBox& from, const std::string &name)
129 // bbmStatus(from.bbmStatus),
132 bbmBoxProcessMode(from.bbmBoxProcessMode),
136 bbtkDebugMessage("object",4,"==> BlackBox::BlackBox("
137 <<from.bbGetFullName()<<",\""
138 <<name<<"\")"<<std::endl);
139 bbtkDebugMessage("object",4,"<== BlackBox::BlackBox("
140 <<from.bbGetFullName()<<",\""
141 <<name<<"\")"<<std::endl);
143 //=========================================================================
146 //=========================================================================
147 BlackBox::~BlackBox()
149 bbtkDebugMessage("object",4,"==> BlackBox::~BlackBox() ["<<bbmName
151 this->bbDesallocateConnectors();
152 bbtkDebugMessage("object",4,"<== BlackBox::~BlackBox() ["<<bbmName
155 //=========================================================================
159 //=========================================================================
160 std::string BlackBox::bbGetFullName() const
162 return this->bbGetNameWithParent()+"<"+this->bbGetDescriptor()->GetTypeName()+">";
164 //=========================================================================
168 //=========================================================================
169 /// Returns the name with the name of the parent prepended if any
170 std::string BlackBox::bbGetNameWithParent() const
172 if (bbmParent.lock())
174 return bbmParent.lock()->bbGetNameWithParent() + ":" + bbmName;
181 //=========================================================================
183 //=========================================================================
184 /// Prints the Help on the BlackBox type
185 void BlackBox::bbGetHelp(bool full) const
187 bbGetDescriptor()->GetHelp(full);
189 //=========================================================================
192 //=========================================================================
193 /// Returns true if the UserBlackBox has an input of name name
194 bool BlackBox::bbHasInput(const std::string& name) const
196 bbtkDebugMessageInc("Kernel",8,
197 "BlackBox::bbHasInput(\""
198 <<name<<"\") ["<<bbGetFullName()<<"]"
200 bool r = ( bbGetDescriptor()->GetInputDescriptorMap().find(name)
201 != bbGetDescriptor()->GetInputDescriptorMap().end());
202 bbtkDebugDecTab("Kernel",8);
205 //=========================================================================
208 //=========================================================================
209 /// Returns true if the UserBlackBox has an output of name name
210 bool BlackBox::bbHasOutput(const std::string& name) const
212 bbtkDebugMessageInc("Kernel",8,"BlackBox::bbHasOutput(\""
213 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
214 bool r = ( bbGetDescriptor()->GetOutputDescriptorMap().find(name)
215 != bbGetDescriptor()->GetOutputDescriptorMap().end());
216 bbtkDebugDecTab("Kernel",8);
219 //=========================================================================
222 //=========================================================================
223 /// Gets the output type of a given name
224 TypeInfo BlackBox::bbGetOutputType( const std::string &name ) const
226 bbtkDebugMessageInc("Kernel",8,
227 "BlackBox::bbGetOutputType(\""
228 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
229 TypeInfo r = bbGetDescriptor()->GetOutputDescriptor(name)->GetTypeInfo();
230 bbtkDebugDecTab("Kernel",8);
233 //=========================================================================
235 //=========================================================================
236 /// Gets the input type of a given name
237 TypeInfo BlackBox::bbGetInputType( const std::string &name ) const
239 bbtkDebugMessageInc("Kernel",8,
240 "BlackBox::bbGetInputType(\""
241 <<name<<"\") ["<<bbGetFullName()<<"]"<<std::endl);
242 TypeInfo r = bbGetDescriptor()->GetInputDescriptor(name)->GetTypeInfo();
243 bbtkDebugDecTab("Kernel",8);
246 //=========================================================================
249 //=========================================================================
250 /// Allocates the i/o connectors of the black box
251 void BlackBox::bbAllocateConnectors()
253 bbtkDebugMessageInc("Kernel",8,
254 "BlackBox::bbAllocateConnectors() ["
255 <<bbGetFullName()<<"]"
257 const BlackBoxDescriptor::InputDescriptorMapType& imap
258 = bbGetDescriptor()->GetInputDescriptorMap();
259 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
260 for ( i = imap.begin(); i != imap.end(); ++i )
262 bbtkDebugMessage("Kernel",8,"* Allocate \""<<i->first<<"\""<<std::endl);
263 bbGetInputConnectorMap()[i->second->GetName()]
264 = new BlackBoxInputConnector(GetThisPointer<BlackBox>());
266 const BlackBoxDescriptor::OutputDescriptorMapType& omap
267 = bbGetDescriptor()->GetOutputDescriptorMap();
268 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
269 for ( o = omap.begin(); o != omap.end(); ++o )
271 bbtkDebugMessage("Kernel",8,"* Allocate \""<<o->first<<"\""<<std::endl);
272 bbGetOutputConnectorMap()[o->second->GetName()]
273 = new BlackBoxOutputConnector();
275 bbtkDebugDecTab("Kernel",8);
277 //=========================================================================
280 //=========================================================================
281 /// Desallocates the i/o connectors of the black box
282 void BlackBox::bbDesallocateConnectors()
284 bbtkDebugMessageInc("Kernel",8,
285 "BlackBox::bbDesallocateConnectors()"
288 InputConnectorMapType::const_iterator i;
289 for ( i = bbGetInputConnectorMap().begin();
290 i != bbGetInputConnectorMap().end(); ++i )
292 bbtkDebugMessage("Kernel",8,"* Delete \""<<i->first<<"\""<<std::endl);
295 OutputConnectorMapType::const_iterator o;
296 for ( o = bbGetOutputConnectorMap().begin();
297 o != bbGetOutputConnectorMap().end(); ++o )
299 bbtkDebugMessage("Kernel",8,"* Delete \""<<o->first<<"\""<<std::endl);
303 bbtkDebugDecTab("Kernel",8);
306 //=========================================================================
309 //=========================================================================
310 /// Copies the input / output values from another box
311 void BlackBox::bbCopyIOValues(BlackBox& from)
313 bbtkDebugMessageInc("Kernel",1,
314 "BlackBox::bbCopyIOValues("
315 <<from.bbGetFullName()<<") ["
316 <<bbGetFullName()<<"]"<<std::endl);
317 // copies the input values
318 const BlackBoxDescriptor::InputDescriptorMapType& imap
319 = bbGetDescriptor()->GetInputDescriptorMap();
320 BlackBoxDescriptor::InputDescriptorMapType::const_iterator i;
321 for ( i = imap.begin(); i != imap.end(); ++i )
323 if (! i->second->GetCopyConstruct() ) continue;
324 std::string input = i->second->GetName();
325 bbtkDebugMessage("Kernel",2,"* Copying input "<<input<<std::endl);
326 this->bbSetInput(input, from.bbGetInput(input) );
328 // copies the output values
329 const BlackBoxDescriptor::OutputDescriptorMapType& omap
330 = bbGetDescriptor()->GetOutputDescriptorMap();
331 BlackBoxDescriptor::OutputDescriptorMapType::const_iterator o;
332 for ( o = omap.begin(); o != omap.end(); ++o )
334 if (! o->second->GetCopyConstruct() ) continue;
335 std::string output = o->second->GetName();
336 bbtkDebugMessage("Kernel",2,"* Copying output "<<output<<std::endl);
337 this->bbSetOutput(output, from.bbGetOutput(output) );
340 bbtkDebugDecTab("Kernel",9);
343 //=========================================================================
347 //=========================================================================
348 bool BlackBox::bbCanReact() const
350 return ( bbGlobalGetSomeBoxExecuting()
352 || Wx::IsSomeWindowAlive()
356 //=========================================================================
360 //=========================================================================
361 /// User overloadable destruction method of a black box
362 void BlackBox::bbUserDelete()
364 bbtkDebugMessage("process",5,
365 "=> BlackBox::bbUserDelete() ["
366 <<bbGetFullName()<<"]"
367 <<" : not overloaded; using standard deletion"
371 //=========================================================================
374 //=========================================================================
375 BlackBox::BoxProcessModeValue BlackBox::bbGetBoxProcessModeValue() const
377 const std::string& p = bbmBoxProcessMode;
379 (p == "P") || (p == "p") ||
380 (p == "Pipeline") || (p == "pipeline") ) return Pipeline;
382 (p == "A") || (p == "a") ||
383 (p == "Always") || (p == "always") ) return Always;
385 (p == "R") || (p == "r") ||
386 (p == "Reactive") || (p == "reactive") ) return Reactive;
389 (p == "F") || (p == "f") ||
390 (p == "Flash") || (p == "flash") ) return Flash;
392 bbtkError(bbGetFullName()<<" : BoxProcessMode value '"<<p
393 <<"' unknown. Possible values : "
394 <<"'0'/'P'/'p'/'Pipeline'/'pipeline' | "
395 <<"'1'/'A'/'a'/'Always'/'always' | "
396 <<"'2'/'R'/'r'/'Reactive'/'reactive'"
397 // <<"'3'/'F'/'f'/'Flash'/'flash'"
400 //=========================================================================
402 //=========================================================================
403 bool BlackBox::bbBoxProcessModeIsReactive() const
405 return (bbGetBoxProcessModeValue() == Reactive);
407 //=========================================================================
409 //=========================================================================
410 bool BlackBox::bbBoxProcessModeIsAlways() const
412 return (bbGetBoxProcessModeValue() == Always);
414 //=========================================================================
419 //=========================================================================
420 void BlackBox::bbAddOutputObserver(const std::string& output,
421 OutputChangeCallbackType f)
423 bbGetOutputConnector(output).AddChangeObserver(f);
425 //=========================================================================
427 //=========================================================================
428 void BlackBox::bbRemoveOutputObserver(const std::string& output_name,
429 OutputChangeCallbackType f)
431 bbtkError("BlackBox::RemoveChangeObserver NOT IMPLEMENTED");
433 //=========================================================================
437 //=========================================================================
438 /// Sets the ChangeTime of input
439 void BlackBox::bbSetInputChangeTime(BlackBoxInputConnector* c,
442 bbtkDebugMessage("change",1,
443 "==> BlackBox::bbSetInputChangeTime("<<c<<","<<t<<") ["
444 <<bbGetFullName()<<"]"<<std::endl);
446 // If new time is greater than old one
447 if ( c->SetChangeTime(t) )
449 bool was_up_to_date = bbIsUpToDate();
450 // If new time is greater than the old max time of inputs
451 if ( mMaxInputChangeTime.Set(t) )
453 // If the box turned out-of-date
454 if ( was_up_to_date && bbIsOutOfDate() )
457 if ( ( bbBoxProcessModeIsReactive() ||
458 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
461 bbtkDebugMessage("change",2,
464 <<" changed and box is in Reactive mode or BoxExecute input changed : adding it to the global execution list"
466 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
468 // Have to propagate the modification to aval boxes
469 OutputConnectorMapType::iterator i;
470 for (i = bbGetOutputConnectorMap().begin();
471 i != bbGetOutputConnectorMap().end();
474 i->second->SetChangeTime(t);
476 // update the MinOutputChangeTime
477 mMinOutputChangeTime.Set(t);
482 //=========================================================================
484 //=========================================================================
485 /// Sets the ChangeTime of output
486 void BlackBox::bbSetOutputChangeTime(BlackBoxOutputConnector* c,
489 bbtkDebugMessage("change",1,
490 "==> BlackBox::bbSetOutputChangeTime("<<c<<","<<t<<") ["
491 <<bbGetFullName()<<"]"<<std::endl);
495 // c->GetChangeTime() = t;
496 // bbUpdateMinOutputChangeTime(t);
500 //=========================================================================
504 //=========================================================================
505 void BlackBox::bbUpdateMaxInputChangeTime(const ChangeTime& t)
509 if ( t > mMaxInputChangeTime )
511 mMaxInputChangeTime = t;
512 if ( mMinOutputChangeTime > mMaxInputChangeTime )
519 //=========================================================================
521 //=========================================================================
522 void bbUpdateMinOutputChangeTime(const ChangeTime& t)
524 ChangeTime old = mMinOutputChangeTime;
525 mMinOutputChangeTime = MAXLONG;
526 OutputConnectorMapType::iterator i;
527 for (i = bbGetOutputConnectorMap.begin();
528 i != bbGetOutputConnectorMap.end();
531 if (i->second->GetChangeTime() < mMinOutputChangeTime)
532 mMinOutputChangeTime = i->second->GetChangeTime();
534 if ( mMinOutputChangeTime < old )
539 //=========================================================================
542 //=========================================================================
543 /// Signals that the BlackBox has been modified through
544 /// the input connector c
545 /// and propagates it downward
546 /// ** NOT USER INTENDED **
547 void BlackBox::bbSetStatusAndPropagate(BlackBoxInputConnector* c,
550 bbtkDebugMessageInc("change",5,
551 "=> BlackBox::bbSetStatusAndPropagate(input,"
552 <<GetIOStatusString(s)<<") ["
553 <<bbGetFullName()<<"]"<<std::endl);
555 if (s==UPTODATE) bbtkError("bbSetStatusAndPropagate with status UPTODATE!");
560 if (bbGetBoxProcessModeValue() == Flash)
566 OutputConnectorMapType::const_iterator o;
567 for ( o = bbGetOutputConnectorMap().begin();
568 o != bbGetOutputConnectorMap().end(); ++o )
570 if (o->second->GetStatus()==UPTODATE)
572 o->second->SetStatus(OUTOFDATE);
573 o->second->SignalChange(GetThisPointer<BlackBox>(),o->first);
577 if ( ( bbBoxProcessModeIsReactive() ||
578 (c==bbGetInputConnectorMap().find("BoxExecute")->second))
581 bbtkDebugMessage("change",2,
582 "-> Execution triggered by Reactive mode or BoxExecute input change"<<std::endl);
583 bbGlobalAddToExecutionList( GetThisPointer<BlackBox>() );
585 bbtkDebugMessageInc("change",5,
586 "<= BlackBox::bbSetStatusAndPropagate(input) ["
587 <<bbGetFullName()<<"]"<<std::endl);
589 //=========================================================================
592 //=========================================================================
593 void BlackBox::bbSignalOutputModification(bool reaction)
595 bbtkDebugMessageInc("change",5,
596 "=> BlackBox::bbSignalOutputModification("
598 <<bbGetFullName()<<"]"<<std::endl);
600 OutputConnectorMapType::iterator i;
601 for ( i = bbGetOutputConnectorMap().begin();
602 i != bbGetOutputConnectorMap().end(); ++i)
604 // std::cout << "Stat = "
605 //<<GetIOStatusString(i->second->GetStatus())
607 // LG : CANNOT SIGNAL ONLY WHEN UPTODATE
608 // See bbtkSampleOutputObserver
609 // if (i->second->GetStatus()==UPTODATE)
611 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
615 if (reaction) bbGlobalProcessExecutionList();
617 bbtkDebugMessageDec("change",5,
618 "<= BlackBox::bbSignalOutputModification() ["
619 <<bbGetFullName()<<"]"<<std::endl);
622 //=========================================================================
623 //=========================================================================
624 void BlackBox::bbSignalOutputModification(const std::string& output,
627 bbtkDebugMessageInc("change",5,
628 "=> BlackBox::bbSignalOutputModification("
629 <<output<<","<<reaction<<") ["
630 <<bbGetFullName()<<"]"<<std::endl);
632 OutputConnectorMapType::iterator i =
633 bbGetOutputConnectorMap().find(output);
636 if ( i == bbGetOutputConnectorMap().end() )
638 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<output<<") : unknown output");
641 // if (i->second->GetStatus()==UPTODATE)
643 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
644 // Has to notify the output "BoxChange" also
645 if (output != "BoxChange")
647 i = bbGetOutputConnectorMap().find("BoxChange");
648 if ( i != bbGetOutputConnectorMap().end() )
650 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
653 if (reaction) bbGlobalProcessExecutionList();
656 bbtkDebugMessageDec("change",5,
657 "<= BlackBox::bbSignalOutputModification("
659 <<bbGetFullName()<<"]"<<std::endl);
662 //=========================================================================
663 //=========================================================================
664 void BlackBox::bbSignalOutputModification(const std::vector<std::string>& output,
667 bbtkDebugMessageInc("change",5,
668 "=> BlackBox::bbSignalOutputModification(vector of outputs) ["
669 <<bbGetFullName()<<"]"<<std::endl);
670 OutputConnectorMapType::iterator i;
671 std::vector<std::string>::const_iterator o;
672 bool changed = false;
673 for (o=output.begin();o!=output.end();++o)
675 // the output "BoxChange" must be signaled **AFTER** all others
676 if (*o == "BoxChange") continue;
677 // Look for the connector
678 i = bbGetOutputConnectorMap().find(*o);
679 if ( i == bbGetOutputConnectorMap().end() )
681 bbtkError("BlackBox["<<bbGetFullName()<<"]::bbSignalOutputModification("<<*o<<") : unknown output");
684 // if (i->second->GetStatus()==UPTODATE)
686 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
690 // Has to notify the output "BoxChange" also
691 i = bbGetOutputConnectorMap().find("BoxChange");
692 if ( changed && (i != bbGetOutputConnectorMap().end()))
694 // if (i->second->GetStatus()==UPTODATE)
696 i->second->SignalChange(GetThisPointer<BlackBox>(),i->first);
697 if (reaction) bbGlobalProcessExecutionList();
701 bbtkDebugMessageDec("change",5,
702 "<= BlackBox::bbSignalOutputModification(vector of outputs) ["
703 <<bbGetFullName()<<"]"<<std::endl);
706 //=========================================================================
714 //=========================================================================
715 /// Main processing method of the box.
716 void BlackBox::bbExecute(bool force)
718 bbtkDebugMessageInc("process",2,
719 "=> BlackBox::bbExecute("<<(int)force<<") ["
720 <<bbGetFullName()<<"]"<<std::endl);
722 // If already executing : return
724 if (bbGetExecuting())
726 bbtkDebugMessage("process",2,
727 " -> already executing : abort"<<std::endl);
732 // If execution frozen : return
733 if (bbGlobalGetFreezeExecution())
735 bbtkDebugMessage("process",2,
736 " -> FreezeExecution global flag is 'true' : abort execution"<<std::endl);
741 // If force is true then update is triggered even if the box is UPTODATE
742 // if (force) bbSetModifiedStatus();
744 // Calls the main recursive execution method
745 bbRecursiveExecute(Connection::Pointer());
747 bbtkDebugMessageDec("process",2,
748 "<= BlackBox::bbExecute() ["
749 <<bbGetFullName()<<"]"<<std::endl);
751 //=========================================================================
754 //=========================================================================
755 /// Main recursive processing method of the box.
756 void BlackBox::bbRecursiveExecute( Connection::Pointer caller )
758 bbtkDebugMessageInc("process",3,
759 "=> BlackBox::bbRecursiveExecute("
760 <<(caller?caller->GetFullName():"0")<<") ["
761 <<bbGetFullName()<<"]"<<std::endl);
763 // If already executing : return
764 if (bbGetExecuting())
766 bbtkDebugMessage("process",3,
767 " -> already executing : abort"<<std::endl);
771 bbSetExecuting(true);
772 bool wasExecuting = bbGlobalGetSomeBoxExecuting();
773 bbGlobalSetSomeBoxExecuting(true);
775 // Creates the window if the black box has one
776 this->bbCreateWindow();
778 // Updates its inputs
779 IOStatus s = bbUpdateInputs();
781 if ( (s != UPTODATE) ||
782 bbBoxProcessModeIsAlways() )
784 // Displays the window (WxBlackbox)
785 // bbShowWindow(caller);
787 // Actual processing (virtual)
791 // Update the I/O statuses
792 bbComputePostProcessStatus();
796 // Test output status...
797 OutputConnectorMapType::iterator o;
798 for ( o = bbGetOutputConnectorMap().begin();
799 o!= bbGetOutputConnectorMap().end(); ++o)
801 if (o->second->GetStatus() != UPTODATE)
803 bbtkWarning("BlackBox::bbRecursiveExecute ["
805 <<"] : all inputs are Up-to-date but output '"
806 <<o->first<<"' is Out-of-date ???");
810 bbtkDebugMessage("process",3," -> Up-to-date : nothing to do"
814 // Shows the window if the black box has one
815 this->bbShowWindow();
818 bbtkDebugMessage("process",3,
819 "<= BlackBox::bbRecursiveExecute() ["
820 <<bbGetFullName()<<"]"<<std::endl);
822 bbSetExecuting(false);
823 bbGlobalSetSomeBoxExecuting(wasExecuting);
828 //=========================================================================
834 //=========================================================================
835 /// Updates the BlackBox inputs
836 /// Calls RecursiveExecute on all BlackBoxInputConnector
837 /// \returns The maximum of final IOStatus after each input update
838 IOStatus BlackBox::bbUpdateInputs()
840 bbtkDebugMessageInc("process",4,
841 "=> BlackBox::bbUpdateInputs() ["
842 <<bbGetFullName()<<"]"
845 IOStatus s = UPTODATE;
847 InputConnectorMapType::iterator i;
848 for ( i = bbGetInputConnectorMap().begin();
849 i!= bbGetInputConnectorMap().end(); ++i)
851 // if (i->first=="WinHide") continue;
852 // If input type is Void : no recurse
853 //if ( bbGetDescriptor()->GetInputDescriptor(i->first)->GetTypeInfo()
856 bbtkDebugMessageDec("change",2,
857 bbGetName()<<"."<<i->first
858 <<" ["<<i->second<<"] "
859 <<" status before update = '"
860 <<GetIOStatusString(i->second->GetStatus())
862 i->second->RecursiveExecute();
863 IOStatus t = i->second->GetStatus();
865 bbtkDebugMessageDec("change",2,
866 bbGetName()<<"."<<i->first
867 <<" ["<<i->second<<"] "
868 <<" status before process = '"
869 <<GetIOStatusString(i->second->GetStatus())
873 bbtkDebugMessageDec("process",4,
874 "<= BlackBox::bbUpdateInputs() ["
875 <<bbGetFullName()<<"]"
881 //=========================================================================
883 //==================================================================
884 /// Computes the final IOStatus of inputs and outputs after processing
885 void BlackBox::bbComputePostProcessStatus()
887 bbtkDebugMessageInc("process",4,
888 "=> BlackBox::bbComputePostProcessStatus() ["
889 <<bbGetFullName()<<"]"
892 IOStatus new_output_status = UPTODATE;
893 if (bbBoxProcessModeIsAlways()) new_output_status = OUTOFDATE;
895 // Update the input statuses
896 InputConnectorMapType::iterator i;
897 for ( i = bbGetInputConnectorMap().begin();
898 i!= bbGetInputConnectorMap().end(); ++i)
900 IOStatus t = i->second->GetStatus();
901 if (t == OUTOFDATE) new_output_status = OUTOFDATE;
902 // A previously MODIFIED status turns to UPTODATE
903 if (t==MODIFIED) i->second->SetStatus(UPTODATE);
904 bbtkDebugMessage("change",2,
905 bbGetName()<<"."<<i->first<<" : "
906 << GetIOStatusString(t) << " -> "
907 << GetIOStatusString(i->second->GetStatus())
910 bbtkDebugMessage("change",2,
911 bbGetName()<<" new output status : "
912 << GetIOStatusString(new_output_status)
914 // Update the output statuses
915 OutputConnectorMapType::iterator o;
916 for ( o = bbGetOutputConnectorMap().begin();
917 o!= bbGetOutputConnectorMap().end(); ++o)
919 o->second->SetStatus(new_output_status);
922 bbtkDebugMessageInc("process",4,
923 "<= BlackBox::bbComputePostProcessStatus() ["
924 <<bbGetFullName()<<"]"
928 //==================================================================
930 //=========================================================================
931 /// Connects the input <name> to the connection c
932 void BlackBox::bbConnectInput( const std::string& name, Connection* c)
934 bbtkDebugMessage("connection",2,
935 "==> BlackBox::bbConnectInput(\""
936 <<name<<"\","<<c->GetFullName()<<") ["
937 <<bbGetFullName()<<"]"
941 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
942 if (i==bbGetInputConnectorMap().end())
944 bbtkError("no input called '"<<name<<"'");
946 i->second->SetConnection(c);
947 // The input *MUST* be set OUTOFDATE to update its input on next execution
948 bbSetStatusAndPropagate(i->second,OUTOFDATE);
950 bbtkDebugMessage("connection",2,
951 "<== BlackBox::bbConnectInput(\""
952 <<name<<"\","<<c->GetFullName()<<") ["
953 <<bbGetFullName()<<"]"
957 //=========================================================================
960 //=========================================================================
961 /// Connects the output <name> to the connection c
962 void BlackBox::bbConnectOutput( const std::string& name, Connection* c)
964 bbtkDebugMessage("connection",2,
965 "==> BlackBox::bbConnectOutput(\""<<name<<"\","
966 <<c->GetFullName()<<") ["
967 <<bbGetFullName()<<"]"<<std::endl);
969 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
970 if (i==bbGetOutputConnectorMap().end())
972 bbtkError("no output called '"<<name<<"'");
974 i->second->SetConnection(c);
976 bbtkDebugMessage("connection",2,
977 "<== BlackBox::bbConnectOutput(\""<<name<<"\","
978 <<c->GetFullName()<<") ["
979 <<bbGetFullName()<<"]"<<std::endl);
982 //=========================================================================
985 //=========================================================================
986 /// Disconnects the input <name> from the connection c
987 void BlackBox::bbDisconnectInput( const std::string& name, Connection* c)
990 bbtkDebugMessage("connection",2,
991 "==> BlackBox::bbDisconnectInput(\""<<name
992 <<"\","<<c->GetFullName()<<") ["
993 <<bbGetFullName()<<"]"
999 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1003 InputConnectorMapType::iterator i = bbGetInputConnectorMap().find(name);
1004 if (i==bbGetInputConnectorMap().end())
1006 bbtkError("no input called '"<<name<<"'");
1008 i->second->UnsetConnection(c);
1010 bbtkDebugMessage("connection",2,
1011 "<== BlackBox::bbDisconnectInput(\""<<name
1012 <<"\","<<c->GetFullName()<<") ["
1013 <<bbGetFullName()<<"]"
1017 //=========================================================================
1020 //=========================================================================
1021 /// Disconnects the output <name> from the connection c
1022 void BlackBox::bbDisconnectOutput( const std::string& name, Connection* c)
1024 bbtkDebugMessage("connection",2,
1025 "==> BlackBox::bbDisconnectOutput(\""<<name
1026 <<"\","<<c->GetFullName()<<") ["
1027 <<bbGetFullName()<<"]"
1032 bbtkDebugMessage("connection",2,"c==0"<<std::endl);
1036 OutputConnectorMapType::iterator i = bbGetOutputConnectorMap().find(name);
1037 if (i==bbGetOutputConnectorMap().end())
1039 bbtkError("no output called '"<<name<<"'");
1041 i->second->UnsetConnection(c);
1043 bbtkDebugMessage("connection",2,
1044 "<== BlackBox::bbDisconnectOutput(\""<<name
1045 <<"\","<<c->GetFullName()<<") ["
1046 <<bbGetFullName()<<"]"
1049 //=========================================================================
1052 //=========================================================================
1054 void BlackBox::bbWriteDotInputOutputName(FILE *ff,bool inputoutput,int detail, int level)
1056 fprintf(ff,"%s%p",bbGetTypeName().c_str(),this);
1058 //=========================================================================
1061 //=========================================================================
1062 std::string BlackBox::bbGetOutputAsString( const std::string &output )
1065 // Looks for the adaptor
1066 if (bbGetOutputType(output).name() != typeid(std::string).name() )
1069 Package::Pointer p = bbGetDescriptor()->GetPackage();
1070 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1072 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1073 BlackBox::Pointer a;
1077 bbGetOutputType(output),
1078 typeid(std::string),
1080 } catch (bbtk::Exception e)
1085 a->bbSetInput("In",bbGetOutput(output));
1087 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1089 v="? (no adaptor found)";
1094 v="? (no factory found)";
1100 v = bbGetOutput(output).unsafe_get<std::string>() ;
1104 //=========================================================================
1106 //=========================================================================
1107 std::string BlackBox::bbGetInputAsString( const std::string &input )
1110 // Looks for the adaptor
1111 if (bbGetInputType(input) != typeid(std::string))
1114 Package::Pointer p = bbGetDescriptor()->GetPackage();
1115 if ((p != 0) && ( ! p->GetFactorySet().empty() ) )
1117 Factory::Pointer f = p->GetFactorySet().begin()->lock();
1118 BlackBox::Pointer a;
1122 bbGetInputType(input),
1123 typeid(std::string),
1125 }catch (bbtk::Exception e)
1131 a->bbSetInput("In",bbGetInput(input));
1133 v = a->bbGetOutput("Out").unsafe_get<std::string>() ;
1137 v="? (no adaptor found)";
1142 v="? (no factory found)";
1147 v = bbGetInput(input).unsafe_get<std::string>() ;
1151 //=======================================================================
1153 //=======================================================================
1154 // Replaces substrings "<" by "["
1155 void SubsBrackets ( std::string& s )
1157 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
1158 std::string ss("<");
1159 std::string::size_type pos = 0;
1161 std::string cr("[");
1162 while ( pos != std::string::npos )
1164 // std::cout << "*** find one "<<std::endl;
1165 s.replace(pos,1,cr.c_str(),1);
1166 pos = s.find(ss, pos);
1172 while ( pos != std::string::npos )
1174 // std::cout << "*** find one "<<std::endl;
1175 s.replace(pos,1,cr.c_str(),1);
1176 pos = s.find(ss, pos);
1182 while ( pos != std::string::npos )
1184 // std::cout << "*** find one "<<std::endl;
1185 s.replace(pos,1,cr.c_str(),1);
1186 pos = s.find(ss, pos);
1187 } // std::cout << "AFTER=["<<s<<"]"<<std::endl;
1189 //=======================================================================
1191 //=========================================================================
1192 /// Write Graphviz-dot description in file
1193 void BlackBox::bbWriteDotFileBlackBox(FILE *ff,
1194 BlackBox::Pointer parentblackbox,
1195 int detail, int level,
1196 bool instanceOrtype,
1197 bool relative_link )
1200 InputConnectorMapType::iterator i;
1202 std::string labelStr;
1203 std::string valueStr("");
1206 labelStr = bbGetName() ;
1208 labelStr = labelStr + "\\n[" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "]";
1210 labelStr = bbGetName();
1211 labelStr = labelStr + " [" +this->bbGetDescriptor()->GetPackage()->GetName()+"::"+ bbGetTypeName() + "] ";
1214 SubsBrackets(labelStr);
1217 labelStr = labelStr + " | {{ ";
1218 std::string tempStrTypeName;
1221 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1225 labelStr=labelStr+" | ";
1228 if (instanceOrtype==true)
1230 valueStr = this->bbGetInputAsString(i->first) + " = ";
1232 const BlackBoxInputDescriptor* id = bbGetDescriptor()->GetInputDescriptor(i->first);
1233 tempStrTypeName=id->GetTypeName();
1234 SubsBrackets(tempStrTypeName);
1235 std::string Name(i->first);
1237 labelStr=labelStr + "<"+i->first.c_str()+"> " + valueStr + Name.c_str() + " [" + tempStrTypeName.c_str() + "]";
1239 labelStr=labelStr+ " } | {";
1241 OutputConnectorMapType::iterator ii;
1242 for ( ii = mOutputConnectorMap.begin(); ii != mOutputConnectorMap.end(); ++ii )
1246 labelStr=labelStr+" | ";
1249 if (instanceOrtype==true)
1251 valueStr = this->bbGetOutputAsString(ii->first) + " = ";
1253 const BlackBoxOutputDescriptor* id = bbGetDescriptor()->GetOutputDescriptor(ii->first);
1254 tempStrTypeName=id->GetTypeName();
1255 SubsBrackets(tempStrTypeName);
1256 std::string Name(ii->first);
1258 labelStr=labelStr+"<"+ii->first.c_str()+"> " + valueStr + Name.c_str() + " ["+tempStrTypeName+"]";
1260 labelStr = labelStr+ " } }" ;
1264 bbWriteDotInputOutputName(ff,true,detail,level);
1265 std::string tmp ( bbGetTypeName() );
1269 url = this->bbGetDescriptor()->GetPackage()->GetDocRelativeURL() + "#" + tmp;
1271 url = this->bbGetDescriptor()->GetPackage()->GetDocURL() + "#" + tmp;
1273 fprintf( ff , " [shape=record, URL=\"%s\",label=\"%s\"]%s\n",url.c_str(),labelStr.c_str(),";" );
1274 // std::cout << labelStr << std::endl;
1277 if (GetThisPointer<BlackBox>()!=parentblackbox){
1278 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1282 Connection* con = i->second->GetConnection();
1284 BlackBox::Pointer a=con->GetOriginalBlackBoxFrom();
1285 BlackBox::Pointer b=con->GetOriginalBlackBoxTo();
1287 a->bbWriteDotInputOutputName(ff,false,detail,level);
1290 fprintf(ff,":%s",con->GetOriginalBlackBoxFromOutput().c_str());
1293 b->bbWriteDotInputOutputName(ff,true,detail,level);
1296 fprintf(ff,":%s",con->GetOriginalBlackBoxToInput().c_str());
1298 fprintf(ff,"%s\n",";");
1302 } // if parentblackbox
1304 //=========================================================================
1309 //=========================================================================
1310 void BlackBox::bbShowRelations(BlackBox::Pointer parentblackbox,
1311 int detail, int level
1312 /*,Factory *factory*/ )
1315 if (this->bbGetDescriptor()->GetPackage())
1317 bbtkMessage("Help",1,"Black Box '"<<bbGetName()<<"' <"<<
1318 this->bbGetDescriptor()->GetPackage()->GetName()
1319 <<"::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1323 bbtkMessage("Help",1,"Black Box <::"<<this->bbGetDescriptor()->GetTypeName()<<">"<<std::endl);
1328 bbtkMessage("Help",1,"Up-to-date ["<<mMaxInputChangeTime<<","
1329 <<mMinOutputChangeTime<<"]"<<std::endl);
1333 bbtkMessage("Help",1,"Out-of-date ["<<mMaxInputChangeTime<<","
1334 <<mMinOutputChangeTime<<"]"<<std::endl);
1337 // bbtkMessage("Help",1," "<<GetDescription()<<std::endl);
1338 // bbtkMessage("Help",1," By : "<<GetAuthor()<<std::endl);
1340 std::vector<std::string> iname;
1341 std::vector<std::string> ivalue;
1342 std::vector<std::string> iconn;
1343 std::vector<std::string> istatus;
1345 InputConnectorMapType::iterator i;
1346 unsigned int namelmax = 0;
1347 unsigned int valuelmax = 0;
1348 // unsigned int connlmax = 0;
1349 for ( i = mInputConnectorMap.begin(); i != mInputConnectorMap.end(); ++i )
1351 iname.push_back(i->first);
1352 if (iname.back().size()>namelmax) namelmax = iname.back().size();
1353 ivalue.push_back(bbGetInputAsString(i->first));
1354 if (ivalue.back().size()>valuelmax) valuelmax = ivalue.back().size();
1356 Connection* con = i->second->GetConnection();
1358 s = con->GetOriginalBlackBoxFrom()->bbGetName();
1360 s += con->GetOriginalBlackBoxFromOutput();
1363 istatus.push_back(GetIOStatusString(i->second->GetStatus()));
1365 OutputConnectorMapType::iterator o;
1366 std::vector<std::string> oname;
1367 std::vector<std::string> ovalue;
1368 std::vector<std::vector<std::string> > oconn;
1369 std::vector<std::string> ostatus;
1370 for ( o = mOutputConnectorMap.begin(); o != mOutputConnectorMap.end(); ++o )
1372 oname.push_back(o->first);
1373 if (oname.back().size()>namelmax) namelmax = oname.back().size();
1374 ovalue.push_back(bbGetOutputAsString(o->first));
1375 if (ovalue.back().size()>valuelmax) valuelmax = ovalue.back().size();
1376 std::vector<std::string> ss;
1377 const std::vector<Connection*>& con
1378 = o->second->GetConnectionVector();
1379 std::vector<Connection*>::const_iterator c;
1380 for (c=con.begin();c!=con.end();++c)
1383 s = (*c)->GetOriginalBlackBoxTo()->bbGetName();
1385 s += (*c)->GetOriginalBlackBoxToInput();
1388 oconn.push_back(ss);
1389 ostatus.push_back(GetIOStatusString(o->second->GetStatus()));
1393 bbtkMessage("Help",1," * Inputs : "<<std::endl);
1395 bbtkMessage("Help",1," * No inputs"<<std::endl);
1397 std::vector<std::string>::iterator i1,i2,i3,i4;
1398 for (i1=iname.begin(),i2=ivalue.begin(),i3=iconn.begin(),i4=istatus.begin();
1399 i1!=iname.end(),i2!=ivalue.end(),i3!=iconn.end(),i4!=istatus.end();
1400 ++i1,++i2,++i3,++i4)
1402 std::string name(*i1);
1404 name.append(1+namelmax-name.size(),' ');
1405 std::string value(*i2);
1407 value.append(1+valuelmax-value.size(),' ');
1409 bbtkMessage("Help",1," '"<<name<<" = '"<<value<<" <-- '"
1412 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1413 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1417 bbtkMessage("Help",1," * Outputs : "<<std::endl);
1419 bbtkMessage("Help",1," * No outputs"<<std::endl);
1421 std::vector<std::vector<std::string> >::iterator i5;
1423 for (i1=oname.begin(),i2=ovalue.begin(),i5=oconn.begin(),i4=ostatus.begin();
1424 i1!=oname.end(),i2!=ovalue.end(),i5!=oconn.end(),i4!=ostatus.end();
1425 ++i1,++i2,++i4,++i5)
1427 std::string name(*i1);
1429 name.append(1+namelmax-name.size(),' ');
1430 std::string value(*i2);
1432 value.append(1+valuelmax-value.size(),' ');
1434 bbtkMessage("Help",1," '"<<name<<" = '"<<value);
1437 std::string pref = " '"+name+" = '"+value;
1438 for (i3=i5->begin();i3!=i5->end();++i3)
1440 bbtkMessage("Help",1,pref<<" --> '"<<*i3<<"'");
1441 pref.replace(0,pref.size(),pref.size(),' ');
1444 bbtkMessage("Help",1," ["<<*i4<<"]"<<std::endl);
1448 //=========================================================================
1450 static bool bbmgGlobalProcessingExecutionList = false;
1452 //=========================================================================
1453 void BlackBox::bbGlobalProcessExecutionList()
1455 bbtkDebugMessageInc("process",3,
1456 "=> BlackBox::bbGlobalProcessExecutionList()"
1458 if (bbmgGlobalProcessingExecutionList)
1460 bbtkDebugMessage("process",3,"BlackBox::bbGlobalProcessExecutionList() reentered !");
1463 bbmgGlobalProcessingExecutionList = true;
1465 std::set<BlackBox::WeakPointer>::iterator i;
1466 while (bbmgExecutionList.size()>0)
1468 i = bbmgExecutionList.begin();
1469 BlackBox::WeakPointer p = *i;
1470 bbmgExecutionList.erase(i);
1473 bbtkDebugMessage("process",4,
1475 p.lock()->bbGetFullName()<<std::endl);
1476 p.lock()->bbExecute(true);
1480 bbtkGlobalError("Strange error in BlackBox::bbGlobalProcessExecutionList() : Weak bb pointer in bbmgExecutionList is no more valid...");
1484 bbmgExecutionList.clear();
1485 bbtkDebugMessageDec("process",3,
1486 "<= BlackBox::bbGlobalProcessExecutionList()"
1489 bbmgGlobalProcessingExecutionList = false;
1492 //=========================================================================
1494 bool BlackBox::bbGlobalGetSomeBoxExecuting()
1496 return bbmgSomeBoxExecuting;
1499 void BlackBox::bbGlobalSetSomeBoxExecuting(bool b)
1501 bbmgSomeBoxExecuting = b;
1504 void BlackBox::bbGlobalSetFreezeExecution(bool b)
1506 bbmgFreezeExecution = b;
1509 bool BlackBox::bbGlobalGetFreezeExecution()
1511 return bbmgFreezeExecution;
1514 void BlackBox::bbGlobalAddToExecutionList( BlackBox::Pointer b )
1516 bbtkDebugMessage("process",3,"* bbGlobalAddToExecutionList("<<b->bbGetFullName()<<")"<<std::endl);
1517 if (bbmgGlobalProcessingExecutionList)
1519 bbtkDebugMessage("process",3,"bbGlobalAddToExecutionList called inside bbGlobalProcessExecutionList !");
1521 bbmgExecutionList.insert(b);
1525 //=========================================================================
1527 //=========================================================================
1528 void BlackBox::Check(bool recursive)
1530 bbtkMessage("debug",1,"*** Checking Black Box "<<(void*)this<<" ["<<bbGetFullName()
1531 <<"] ... OK"<<std::endl);
1533 //=========================================================================
1535 void BlackBox::bbUserOnShowWidget(std::string nameInput)
1537 bbtk::BlackBoxInputConnector *cc;
1538 cc = this->bbGetInputConnectorMap().find( nameInput.c_str() )->second;
1539 if (cc->GetConnection()!=NULL)
1541 cc->GetConnection()->GetBlackBoxFrom()->bbUserOnShow();
1547 } // EO namespace bbtk